std::enable_if 不能用于禁用此声明
std::enable_if cannot be used to disable this declaration
我有一段相当复杂的代码,我将其简化为这个复制器:
#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();
我尝试了一些变体,但没有任何效果。
我阅读了一些已经发布的问答,例如:
或
但他们似乎没有回答我的问题。
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 可以对您想要的 struct/class(或函数或方法)的模板参数进行测试 enable/disable。
您的原始代码中的问题是 SFINAE 测试仅考虑 TA
和 TB
,它们是包含 problem
的 inner
结构中定义的类型。因此测试仅依赖于外部模板参数(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
本身的模板参数的测试中。
如评论中所建议,使用 if constexpr
(C++17 的一部分)使代码更简单:
template<typename ...As>
struct outer {
template<typename ...Bs>
struct inner {
using TA = std::tuple<As...>;
using TB = std::tuple<Bs...>;
struct problem
{
static constexpr auto val()
{
if constexpr (std::tuple_size<TA>::value < std::tuple_size<TB>::value)
return 1; // Complex function goes here
else
return 0; // Other complex function (?) goes here
}
};
};
};
正如@unimportant 评论的那样:if-constexpr 自 C++17 以来。允许您摆脱 dummy
和更多行:
#include <type_traits>
#include <tuple>
template<typename ...As>
struct outer {
template<typename ...Bs>
struct inner {
using TA = std::tuple<As...>;
using TB = std::tuple<Bs...>;
static constexpr auto val() {
if constexpr (std::tuple_size_v<TA> >= std::tuple_size_v<TB>) {
return 0;
}
else {
return 1;
}
}
};
};
int main() {
return outer<int, float>::inner<double>::val();
}
The program '[4544] main.exe' has exited with code 0 (0x0).
我有一段相当复杂的代码,我将其简化为这个复制器:
#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();
我尝试了一些变体,但没有任何效果。
我阅读了一些已经发布的问答,例如:
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 可以对您想要的 struct/class(或函数或方法)的模板参数进行测试 enable/disable。
您的原始代码中的问题是 SFINAE 测试仅考虑 TA
和 TB
,它们是包含 problem
的 inner
结构中定义的类型。因此测试仅依赖于外部模板参数(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
本身的模板参数的测试中。
如评论中所建议,使用 if constexpr
(C++17 的一部分)使代码更简单:
template<typename ...As>
struct outer {
template<typename ...Bs>
struct inner {
using TA = std::tuple<As...>;
using TB = std::tuple<Bs...>;
struct problem
{
static constexpr auto val()
{
if constexpr (std::tuple_size<TA>::value < std::tuple_size<TB>::value)
return 1; // Complex function goes here
else
return 0; // Other complex function (?) goes here
}
};
};
};
正如@unimportant 评论的那样:if-constexpr 自 C++17 以来。允许您摆脱 dummy
和更多行:
#include <type_traits>
#include <tuple>
template<typename ...As>
struct outer {
template<typename ...Bs>
struct inner {
using TA = std::tuple<As...>;
using TB = std::tuple<Bs...>;
static constexpr auto val() {
if constexpr (std::tuple_size_v<TA> >= std::tuple_size_v<TB>) {
return 0;
}
else {
return 1;
}
}
};
};
int main() {
return outer<int, float>::inner<double>::val();
}
The program '[4544] main.exe' has exited with code 0 (0x0).