使用默认参数的模板专业化

时间:2014-04-03 04:51:39

标签: c++ templates

以下代码编译。有谁能解释为什么?我一直在挖掘标准,以找出合法的原因。

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;

未定义,因此导致错误。

4 个答案:

答案 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();
}