我有一段非常复杂的代码,我将其简化为这个复制器:
#include <type_traits>
#include <tuple>
template<typename ...As>
struct outer {
template<typename ...Bs>
struct inner {
template<bool dummy, typename E = void>
struct problem;
using TA = std::tuple<As...>;
using TB = std::tuple<Bs...>;
template<bool dummy>
struct problem<dummy, typename std::enable_if<std::tuple_size<TA>::value < std::tuple_size<TB>::value>::type>
{
static constexpr auto val() { return 1; } // actually a complex function
};
template<bool dummy>
struct problem<dummy, typename std::enable_if<std::tuple_size<TA>::value >= std::tuple_size<TB>::value>::type>
{
static constexpr auto val() { return 0; }
};
};
};
int main() {
return outer<int, float>::inner<double>::problem<false>::val();
}
它不编译(使用 gcc 或 clang),说:
<source>:13:82: error: failed requirement 'std::tuple_size<std::tuple<int, float> >::value < std::tuple_size<std::tuple<double> >::value'; 'enable_if' cannot be used to disable this declaration
struct problem<dummy, typename std::enable_if<std::tuple_size<TA>::value <std::tuple_size<TB>::value>::type>
~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:27:31: note: in instantiation of template class 'outer<int, float>::inner<double>' requested here
return outer<int, float>::inner<double>::problem<false>::val();
我尝试了一些变体,但没有任何效果。
我阅读了一些已经发布的问答,例如:
this one
或 this one
但他们似乎没有回答我的问题。
PS:我可以使用 C++17,但这必须适用于任何编译器。
最佳答案
建议:尝试如下
struct inner {
using TA = std::tuple<As...>;
using TB = std::tuple<Bs...>;
template<bool dummy, typename UA = TA, typename E = void>
struct problem;
template<bool dummy, typename UA>
struct problem<dummy, UA,
std::enable_if_t<(std::tuple_size_v<UA> < std::tuple_size_v<TB>)>>
{ static constexpr auto val() { return 1; } };
template<bool dummy, typename UA>
struct problem<dummy, UA,
std::enable_if_t<(std::tuple_size_v<UA> >= std::tuple_size_v<TB>)>>
{ static constexpr auto val() { return 0; } };
};
我的意思是......考虑到 SFINAE 对您想要启用/禁用的结构/类(或函数或方法)的模板参数进行测试。
原始代码中的问题是 SFINAE 测试仅考虑
TA
和 TB
,它们是在包含 inner
的 problem
结构中定义的类型。因此,测试仅取决于外部模板参数( As...
和 Bs...
),而不取决于 problem
的模板参数。为
problem
添加具有默认值的模板参数// ..................VVVVVVVVVVVVVVVVV
template<bool dummy, typename UA = TA, typename E = void>
struct problem;
不会改变
problem
本身的实际使用,而是转换 std::enable_if
中的测试template<bool dummy, typename UA>
struct problem<dummy, UA, // ..........VV UA, not TA
std::enable_if_t<(std::tuple_size_v<UA> < std::tuple_size_v<TB>)>>
{ static constexpr auto val() { return 1; } };
在涉及
problem
本身的模板参数的测试中。关于c++ - std::enable_if 不能用于禁用此声明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56444569/