gpt4 book ai didi

c++ - 如何使 static_assert 与 SFINAE 配合使用

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:43:17 25 4
gpt4 key购买 nike

更新

我发布了 rebind 的工作草稿作为问题的答案。虽然我没有太多运气找到一种通用的方法来保留 static_assert s 来自破坏元功能。


基本上我想检查模板类型是否为 T<U, Args...>可以从其他类型构造T<V, Args...> .在哪里TArgs...两种类型都相同。问题是,T<>可能有一个 static_assert其中完全破坏了我的元功能。

下面是我正在尝试做的事情的粗略总结。

template<typename T>
struct fake_alloc {
using value_type = T;
};

template<typename T, typename Alloc = fake_alloc<T>>
struct fake_cont {
using value_type = T;
// comment the line below out, and it compiles, how can I get it to compile without commenting this out???
static_assert(std::is_same<value_type, typename Alloc::value_type>::value, "must be the same type");
};

template<typename T, typename U, typename = void>
struct sample_rebind {
using type = T;
};

template<template<typename...> class Container, typename T, typename U, typename... OtherArgs>
struct sample_rebind<
Container<T, OtherArgs...>,
U,
std::enable_if_t<
std::is_constructible<
Container<T, OtherArgs...>,
Container<U, OtherArgs...>
>::value
>
>
{
using type = Container<U, OtherArgs...>;
};

static_assert(
std::is_same<
fake_cont<int, fake_alloc<int>>,
typename sample_rebind<fake_cont<int>, double>::type
>::value,
"This should pass!"
);

如您所见,所需的行为是最终的 static_assert应该通过,但不幸的是,它甚至没有达到 static_assert 的那一点。在 fake_contstd::is_constructible<> 时触发尝试调用 fake_cont的构造函数。

在真实代码中fake_cont是 libc++ 的 std::vector ,所以我无法修改它的内容,或者 std::is_constructible的胆量。

感谢任何解决此特定问题的建议,以及有关 SFINAE 的一般建议 static_assert特别感谢。

编辑:is_same 的第一部分应该是 fake_cont<int, fake_alloc<int>>

编辑 2:如果您注释掉 static_assertfake_cont ,它编译(clang 3.5)。这就是我想要的。所以我只需要一些方法来避免 static_assertfake_cont .

最佳答案

namespace details {
template<class T,class=void>
struct extra_test_t: std::true_type {};
}

然后我们折叠一个额外的测试:

template<class...>struct types{using type=types;};

template<template<typename...> class Container, typename T, typename U, typename... OtherArgs>
struct sample_rebind<
Container<T, OtherArgs...>,
U,
std::enable_if_t<
details::extra_test_t< types< Container<T, OtherArgs...>, U > >::value
&& std::is_constructible<
Container<T, OtherArgs...>,
Container<U, OtherArgs...>
>::value
>
> {
using type = Container<U, OtherArgs...>;
};

然后我们编写额外的测试:

namespace details {
template<class T, class Alloc, class U>
struct extra_test_t<
types<std::vector<T,Alloc>, U>,
typename std::enable_if<
std::is_same<value_type, typename Alloc::value_type>::value
>::type
> : std::true_type {};
template<class T, class Alloc, class U>
struct extra_test_t<
types<std::vector<T,Alloc>, U>,
typename std::enable_if<
!std::is_same<value_type, typename Alloc::value_type>::value
>::type
> : std::false_type {};
}

基本上,这让我们可以在测试中注入(inject)“补丁”以匹配 static_assert .

如果我们有 is_std_container<T>get_allocator<T> ,我们可以这样写:

namespace details {
template<template<class...>class Z,class T, class...Other, class U>
struct extra_test_t<
types<Z<T,Other...>>, U>,
typename std::enable_if<
is_std_container<Z<T,Other...>>>::value
&& std::is_same<
value_type,
typename get_allocator<Z<T,Other...>>::value_type
>::value
>::type
> : std::true_type {};
template<class T, class Alloc, class U>
struct extra_test_t<
types<std::vector<T,Alloc>, U>,
typename std::enable_if<
is_std_container<Z<T,Other...>>>::value
&& !std::is_same<
value_type,
typename get_allocator<Z<T,Other...>>::value_type
>::value
>::type
> : std::false_type {};
}

或者我们可以声明任何带有 allocator_type 的东西可能无法反弹。

解决此问题的容器感知能力更强的方法是提取分配器类型 ( ::allocator_type ),并用 T 的重新绑定(bind)替换容器参数列表中分配器类型的所有实例。至 U不知何故。这仍然很棘手,因为 std::map<int, int>有一个类型为 std::allocator< std::pair<const int, int> > 的分配器, 并区分键 int和值 int以通用方式是不可能的。

关于c++ - 如何使 static_assert 与 SFINAE 配合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29224823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com