我似乎无法解决以下示例出现的问题
$ cat repro.cpp
#include <iostream>
using namespace std;
template<class T>
struct S1_t
{
template<class U>
struct inner_t_x {};
using inner_t = inner_t_x<T>;
};
struct Bogus{};
template<class T>
struct Functor1
{
void operator()()
{
cout << "Functor1 FAIL: " << __PRETTY_FUNCTION__ << endl;
}
};
template<>
struct Functor1<typename S1_t<Bogus>::template inner_t_x<Bogus>>
{
void operator()()
{
cout << "Functor1 PASS: " << __PRETTY_FUNCTION__ << endl;
}
};
template<class T>
struct Functor2
{
void operator()()
{
cout << "Functor2 FAIL: " << __PRETTY_FUNCTION__ << endl;
}
};
template<class T>
struct Functor2<typename S1_t<T>::template inner_t_x<T>>
{
void operator()()
{
cout << "Functor2 PASS: " << __PRETTY_FUNCTION__ << endl;
}
};
template<class T>
void eval()
{
Functor1<T>{}();
Functor2<T>{}();
}
int main()
{
eval<S1_t<Bogus>::inner_t>();
return 0;
}
$ clang++ repro.cpp -std=c++11 -Wall && ./a.out
Functor1 PASS: void Functor1<S1_t<Bogus>::inner_t_x<Bogus> >::operator()()
Functor2 FAIL: void Functor2<S1_t<Bogus>::inner_t_x<Bogus> >::operator()() [T = S1_t<Bogus>::inner_t_x<Bogus>]
在Functor1
中,我明确地专注于类型Bogus
,实际上正在调用该特化。但是,在Functor2
中允许推导出类型,但部分特化失败并且实例化通用模板。然而,__PRETTY_PRINT__
显示Functor1
&amp;的相同签名。实例化时Functort2
。
任何人都可以解释这种行为吗?有没有办法修复Functor2
部分特化以适应这种情况?谢谢!
fwiw:将Functor2
部分专业化更改为
template<class T>
struct Functor2<typename S1_t<Bogus>::template inner_t_x<T>>
{
void operator()()
{
cout << "Functor2 PASS: " << __PRETTY_FUNCTION__ << endl;
}
};
给出正确的输出
Functor1 PASS: void Functor1<S1_t<Bogus>::inner_t_x<Bogus> >::operator()()
Functor2 PASS: void Functor2<S1_t<Bogus>::inner_t_x<Bogus> >::operator()() [T = S1_t<Bogus>::inner_t_x<Bogus>]
但这不是我用例中的选项。
答案 0 :(得分:4)
typename S1_t<T>::..
在部分专业化中无法推断。
使用inner_t
代替inner_t_x<T>
时,您会收到更明确的错误:
main.cpp:41:8: error: template parameters not deducible in partial specialization:
struct Functor2<typename S1_t<T>::inner_t>
^
main.cpp:41:8: note: 'T'
main.cpp:41:8: warning: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used
答案 1 :(得分:2)
永远不会使用Functor2
的专业化。编译器可以发出关于此的警告,但在您的情况下它并不存在。它不能被推导的原因很简单:想象一下你以后添加类似
struct Hogus;
template<>
struct S1_t<Hogus>
{
template <typename U>
using inner_t_x = S1_t<Bogus>::inner_t_x<Bogus>;
};
然后S1_t<Bogus>::inner_t_x<Bogus>
和S1_t<Hogus>::inner_t_x<Hogus>
属于同一类型。因此,Functor2
的部分特化中的模板推导可以同时产生T=Bogus
或T=Hogus
。因此,在任何情况下都无法毫不含糊地推断出它。