以下代码
#include <iostream>
#include <utility>
template<typename F, typename... T>
struct Wrapper{ };
template<typename T>
struct is_wrapper : std::false_type {};
template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};
//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};
int main()
{
Wrapper<int, double> w;
std::cout << is_wrapper<decltype(w)>::value << std::endl;
}
打印0.但是,如果取消注释中间的两行,则打印1。
为什么不一直打印1?第二部分专业化是否也应该涵盖显然仅由第三(评论)部分专业化所涵盖的案例?
答案 0 :(得分:1)
代码应该与部分特化完全匹配;该标准从未真正禁止这一点,但编译器确实需要一段时间才能正确实现可变参数模板及其演绎。 GCC自4.9.0以来一致,而Clang从3.6开始。 Clang的相关错误报告是#22191(我找不到GCC的。)
答案 1 :(得分:0)
通常,当我编写专门的模板时,我首先使用前向声明,并声明这些案例属于特殊化。在你的情况下,我知道你正在尝试编写一个没有空案例的可变参数模板(也就是说,一个至少有一种类型的可变参数模板)。
您的代码让我感到惊讶,因为我认为您是正确的,您的特征的完全可变特化与洞案例匹配......首先,我尝试使用特征类的前向声明,并且仅定义完全可变的专业化(因此,如果特征的参数不是Wrapper
实例,则编译失败)。而这正是发生的事情,让我再次失望:
#include <iostream>
#include <utility>
template<typename F , typename... T>
struct Wrapper {};
template<typename T>
struct is_wrapper;
//template<typename T>
//struct is_wrapper : std::false_type {};
template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};
//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};
using my_wrapper_type = Wrapper<int,double>;
int main()
{
std::cout << std::boolalpha << is_wrapper<my_wrapper_type>::value << std::endl;
}//"Invalid use of incomplete type" ^^^^^^^^^^^^^^^^^^^^^^^^^^^
最后,我尝试了Wrapper
类中的前向声明方法。令人惊讶的是,它有效:
#include <iostream>
#include <utility>
template<typename... T>
struct Wrapper;
template<typename F, typename... T>
struct Wrapper<F,T...>{ };
template<typename T>
struct is_wrapper : std::false_type {};
template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};
//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};
using my_wrapper_type = Wrapper<int,double>;
int main()
{
std::cout << std::boolalpha << is_wrapper<my_wrapper_type>::value << std::endl;
}
打印:
真
Here是在ideone上运行的代码。
此致,我不明白为什么你的代码失败并且我的工作正常。 它是一个编译器错误,还是我们缺少的东西?我不知道。
答案 2 :(得分:0)
如果我理解你的问题,它只是一个专业化的优先事项,
is_wrapper<decltype(w)>
可以通过2个模板进行专业化:
template<typename T> // exact specialization
template<typename... T> // variadic specialization with one parameter
在这种情况下,编译器优先选择精确的特化,因此模板永远不会在你的情况下实例化。