为什么在声明要使用 `enable_if` 进行专门化的 class 模板时需要 `void`
Why `void` is required while declaring a class template which is to be specialized using `enable_if`
我正在学习 C++ 模板元编程,偶然发现了一个简单的 SFINAE 相关(我相信如此)问题。特别是,我正在编写一个模板 class,它将为我们提供最大尺寸的类型。通过将类型与 sizeof
运算符进行比较,我将 type
别名为正确的类型,具体取决于它们的大小。我正在使用 enable_if
选择正确的 class 专业化。我不明白的是为什么在声明要使用 enable_if
.[=23 专门化的 class 模板时需要将 void
作为 class Enable
的默认值提供=]
以下代码工作正常
// test.cpp
#include <type_traits>
// void works just fine but if changed to anything else say int, compilation fails!
template < typename L, typename R, class Enable = void > struct MaxTypeT;
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) >= sizeof(R)) >::type> {
using type = L;
};
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) < sizeof(R)) >::type> {
using type = R;
};
int main(){
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
return 0;
}
但是当我将 class Enable = void
更改为任何其他类型时说 class Enable = int
,然后我得到以下错误。为什么这里需要void
?
test.cpp: In function ‘int main()’:
test.cpp:17:56: error: incomplete type ‘MaxTypeT<int, double>’ used in nested name specifier
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
^~~~
test.cpp:17:56: error: incomplete type ‘MaxTypeT<int, double>’ used in nested name specifier
test.cpp:17:69: error: template argument 1 is invalid
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
void
不是必需的,它只是为您节省了一些输入时间。如果你想在那里有 int
那么你也许应该这样写:
// test.cpp
#include <type_traits>
// int works just fine now
template < typename L, typename R, typename Enable = int > struct MaxTypeT;
// note additional template argument of enable_if
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) >= sizeof(R)), int >::type> {
using type = L;
};
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) < sizeof(R)), int >::type> {
using type = R;
};
int main(){
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
return 0;
}
enable if
的第二个参数默认为 void
,因此要匹配它,您的模板也必须有 void
或为 enable_if
提供不同的类型.
std::enable_if<>::type
默认为 void
。因此,在模板替换发生后,您的每个特化都有第三个参数 void
。
// primary template
template < typename L, typename R, typename Enable = void > struct MaxTypeT;
// specialization #1
template < typename L, typename R >
struct MaxTypeT<L, R, void> {
using type = L;
};
// specialization #2
template < typename L, typename R >
struct MaxTypeT<L, R, void> {
using type = R;
};
当您执行 MaxTypeT<int, double>
时,它会实例化类型 MaxTypeT<int, double, void>
,因为默认参数 Enable
设置为 void
。
如果 Enable
设置为 int
,它实例化类型 MaxTypeT<int, double, int>
。由于编译器无法将特化与这些参数类型相匹配,因此它与仅声明但未定义的主模板一起使用,因此出现错误。
正如 在他的回答中所说 std::enable_if
有第二个模板参数,指定其 ::type
成员将是什么。如果你将它设置为 int
那么它将是一个特化,在成功的模板替换之后第三个参数为 int
。
我正在学习 C++ 模板元编程,偶然发现了一个简单的 SFINAE 相关(我相信如此)问题。特别是,我正在编写一个模板 class,它将为我们提供最大尺寸的类型。通过将类型与 sizeof
运算符进行比较,我将 type
别名为正确的类型,具体取决于它们的大小。我正在使用 enable_if
选择正确的 class 专业化。我不明白的是为什么在声明要使用 enable_if
.[=23 专门化的 class 模板时需要将 void
作为 class Enable
的默认值提供=]
以下代码工作正常
// test.cpp
#include <type_traits>
// void works just fine but if changed to anything else say int, compilation fails!
template < typename L, typename R, class Enable = void > struct MaxTypeT;
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) >= sizeof(R)) >::type> {
using type = L;
};
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) < sizeof(R)) >::type> {
using type = R;
};
int main(){
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
return 0;
}
但是当我将 class Enable = void
更改为任何其他类型时说 class Enable = int
,然后我得到以下错误。为什么这里需要void
?
test.cpp: In function ‘int main()’:
test.cpp:17:56: error: incomplete type ‘MaxTypeT<int, double>’ used in nested name specifier
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
^~~~
test.cpp:17:56: error: incomplete type ‘MaxTypeT<int, double>’ used in nested name specifier
test.cpp:17:69: error: template argument 1 is invalid
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
void
不是必需的,它只是为您节省了一些输入时间。如果你想在那里有 int
那么你也许应该这样写:
// test.cpp
#include <type_traits>
// int works just fine now
template < typename L, typename R, typename Enable = int > struct MaxTypeT;
// note additional template argument of enable_if
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) >= sizeof(R)), int >::type> {
using type = L;
};
template < typename L, typename R >
struct MaxTypeT<L, R, typename std::enable_if< (sizeof(L) < sizeof(R)), int >::type> {
using type = R;
};
int main(){
static_assert(std::is_same< MaxTypeT<int, double>::type, double >::value, "MaxTypeT not working");
return 0;
}
enable if
的第二个参数默认为 void
,因此要匹配它,您的模板也必须有 void
或为 enable_if
提供不同的类型.
std::enable_if<>::type
默认为 void
。因此,在模板替换发生后,您的每个特化都有第三个参数 void
。
// primary template
template < typename L, typename R, typename Enable = void > struct MaxTypeT;
// specialization #1
template < typename L, typename R >
struct MaxTypeT<L, R, void> {
using type = L;
};
// specialization #2
template < typename L, typename R >
struct MaxTypeT<L, R, void> {
using type = R;
};
当您执行 MaxTypeT<int, double>
时,它会实例化类型 MaxTypeT<int, double, void>
,因为默认参数 Enable
设置为 void
。
如果 Enable
设置为 int
,它实例化类型 MaxTypeT<int, double, int>
。由于编译器无法将特化与这些参数类型相匹配,因此它与仅声明但未定义的主模板一起使用,因此出现错误。
正如 std::enable_if
有第二个模板参数,指定其 ::type
成员将是什么。如果你将它设置为 int
那么它将是一个特化,在成功的模板替换之后第三个参数为 int
。