为什么这个依赖类型不算作使用模板参数的特化?

Jon*_*tte 5 c++ gcc templates specialization

我正在尝试将特化组合在一起,以避免多次编写它们.例如,在下面的代码中,我尝试将"float"和"double"专门化为foo :: func()的一个实现案例; 然后我使用另一个实现"bool".

template<typename T> struct foo;

template<typename T> struct bar;
template<> struct bar<float> { typedef float Type; };
template<> struct bar<double> { typedef double Type; };

/* specialize for float and double here */
template<typename T> struct foo<typename bar<T>::Type> {
    static void func() { ... }
};

template<> struct foo<bool> {
    static void func() { ... }
};
Run Code Online (Sandbox Code Playgroud)

这在GCC 4.4.3中出错.(这是一个目标编译器,因为它是Ubuntu Server 10.04 LTS的库存,据说还有三年的生存时间.)错误是:

foo.cpp:8: error: template parameters not used in partial specialization:
foo.cpp:8: error:         ‘T’
Run Code Online (Sandbox Code Playgroud)

该错误指的是foo的第一个特化(对于"float"和"double".)

我没有看到我在这里违反C++的哪个部分 - 如果有人知道章节和经文,我会很感激.此外,如果有人知道实现相同目标的另一种方式(对某些类型的组重新使用特化,没有不必要的详细代码),我也会感激任何建议!

Naw*_*waz 6

template<typename T> struct foo<typename bar<T>::Type> {
    static void func() { ... }
};
Run Code Online (Sandbox Code Playgroud)

T在非可推导的上下文中使用,因此编译器T即使知道其值也无法推断bar<T>::Type.

假设你写,

foo<double> foodouble;
Run Code Online (Sandbox Code Playgroud)

那么你可能会认为,在实例化时会选择bar哪种专用?这似乎是合理的,只有编译器可以确保不存在另一个定义为嵌套类型的特化,如下所示:doublefoobardouble

template<> struct bar<int> { typedef double Type; };
Run Code Online (Sandbox Code Playgroud)

现在bar<double>::Typebar<int>::Type两个都给double.因此底线是:可能存在无限数量的特化bar,所有这些特化都可以double作为嵌套类型提供,使得编译器无法唯一地推导出bar类模板的模板参数.


您可以将SFINAE用作:

#include <iostream>

template<typename T> struct bar { typedef void type; };
template<> struct bar<float> { typedef bar<float> type; };
template<> struct bar<double> { typedef bar<double> type; };

template<typename T> 
struct foo : bar<T>::type
{
    static void func() 
    { 
        std::cout << "primary template for float and double" << std::endl; 
    }
};

template<> 
struct foo<bool> 
{
    static void func() 
    { 
       std::cout << "specialization for for bool" << std::endl; 
    }
};

int main()
{
     foo<float>::func();
     foo<double>::func();
     foo<bool>::func();
}
Run Code Online (Sandbox Code Playgroud)

输出(在线演示):

primary template for float and double
primary template for float and double
specialization for for bool
Run Code Online (Sandbox Code Playgroud)

请注意,这struct foo : bar<T>::type不再是专业化了.这是一个主要模板.另请注意,它可能不是您想要的,因为它禁用类型参数以外的类模板的所有实例化float,double并且bool; 例如,你不能使用foo<int>.但是我还注意到你已经保留了主模板的未定义,所以我希望这个解决方案符合你的要求.