模板化结构内的模板化结构的模板专业化失败
Template specialisation failure for a templated structure inside a templated structure
我似乎无法理解以下示例出了什么问题
$ 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
和 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>]
但这不是我的用例中的选项。
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
永远不会使用 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
。因此,在任何情况下都不能明确地推导出来。
我似乎无法理解以下示例出了什么问题
$ 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
和 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>]
但这不是我的用例中的选项。
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
永远不会使用 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
。因此,在任何情况下都不能明确地推导出来。