以下代码编译。有谁能解释为什么?我一直在挖掘标准,以找出合法的原因。
template <bool B, typename T = void> struct enable_if { };
template <typename T> struct enable_if<true, T> {
typedef T type;
};
template <typename T, typename Enable = void> struct A;
template <typename T> struct A<T, typename enable_if<(sizeof(T) <= ~0ULL)>::type> {
void f() { }
};
int main() {
A<int> a;
a.f();
}
声明:
A<int> a;
由于只有一个模板参数“int”,编译器应该使用主模板,即:
template <typename T, typename Enable = void> struct A;
未定义,因此导致错误。
答案 0 :(得分:3)
来自§14.5.5.1
1在需要的上下文中使用类模板时 实例化该类,有必要确定是否 实例化将使用主模板或其中一个生成 部分专业化。这是通过匹配模板来完成的 使用模板的类模板特化的参数 部分专业化的参数列表。
- 如果找到一个匹配的特化,则从中生成实例化 专业化。
答案 1 :(得分:1)
让我们试着弄清楚这里发生了什么:
// definition of enable_if, second parameter is defaulted to void
template <bool B, typename T = void>
struct enable_if { };
// specialization of enable_if, if first parameter is true,
// enable_if has a typedef for the second parameter
template <typename T>
struct enable_if<true, T> {
typedef T type;
};
// definition of struct A, second parameter defaults to void
template <typename T, typename Enable = void>
struct A;
// specialization of struct A, second parameter
// is obtained from the enable_if::type typedef
// the first parameter of enable_if is true if the size of T
// is smaller than the max long long (~0 --> all F)
template <typename T>
struct A<T, typename enable_if<(sizeof(T) <= ~0ULL)>::type> {
void f() { }
};
int main() {
// So we attempt the specialization for struct A<int,enable_if...>
// The expression of enable_if evaluates to...
// (sizeof(int) <= ~0ULL) == true
// ... so it applies the specialization of enable_if<true,void>
// (second parameter is void because none is provided, so it
// uses the default.
// so the enable_if template is valid (selected the specialization)
// and that means that the struct A<int,enable_if> specialization
// is valid too, so it is selected.
A<int> a;
a.f();
}
答案 2 :(得分:0)
当您template A<int, enable_if<true>:::type >
评估为A<int>
时,编译器会使用sizeof(int) <= ~0ULL
。{/ p>
true
没有问题,因为编译器可以使用enable_if<true>::type
。
答案 3 :(得分:0)
考虑你的enable_if:
template <bool B, typename T = void> struct enable_if{ };
template <typename T> struct enable_if<true, T>
{
typedef T type;
};
在
void test_EnableIf
{
static_assert(
std::is_same<
enable_if<(sizeof(int) > 0)>::type,
void>::value, "test_EnableIf failed." );
}
结果(类型)是无效的,因为没有指定类型(作为第二个 模板参数)。选择enable_if的特化 因为布尔表达式为true,所以默认值 选择参数(从主模板),因为没有其他参数 提供,因此类型是无效的,但请注意定义 类型确实存在(因为选择了专业化)。
现在,在您对A ...的定义中
template <typename T, typename Enable = void> struct A;
template <typename T>
struct A<T, typename enable_if<
(sizeof(T) <= ~0ULL)>::type>
{
void f() { }
};
...因为类型确实存在于enable_if中,所以它是一个更好的匹配,这会导致选择特化,从而进行编译。
一个简单的例子如下:
template <class T, class U = void>
struct X;
template <class T>
struct X<T,void>
{
static int foo(){ return 0; }
};
int main()
{
return X<int>::foo();
}