类模板部分特化参数化成员函数返回类型
以下代码尝试根据成员函数指针类型的返回类型对类模板“special”进行特化,这会导致 VC9 出现编译错误:
template<class F> struct special {};
template<class C> struct special<void(C::*)()> {};
template<class R, class C> struct special<R(C::*)()> {};
struct s {};
int main()
{
special<void(s::*)()> instance;
return 0;
}
错误 C2752:“特殊”:多个部分特化与模板参数列表匹配
GCC-4.3.4 接受相同的代码,如下所示: http ://ideone.com/ekWGg
这是 VC9 中的错误吗?如果是,这个错误是否仍然存在于 VC10 中?
然而,我想出了一个可怕的侵入性解决方法(至少对于这个特定的用例。欢迎更通用的解决方案):
#include <boost/function_types/result_type.hpp>
#include <boost/type_traits/is_same.hpp>
template<typename F, typename R>
struct is_result_same :
boost::is_same<
typename boost::function_types::result_type<F>::type,
R
>
{};
template<class F, bool = is_result_same<F, void>::value>
struct special {};
template<class R, class C> struct special<R(C::*)(), true> {};
template<class R, class C> struct special<R(C::*)(), false> {};
The following code, which attempts to specialize class template 'special', based on the return type of member function pointer types, results in a compile error with VC9:
template<class F> struct special {};
template<class C> struct special<void(C::*)()> {};
template<class R, class C> struct special<R(C::*)()> {};
struct s {};
int main()
{
special<void(s::*)()> instance;
return 0;
}
error C2752: 'special' : more than one partial specialization matches the template argument list
The same code is accepted by GCC-4.3.4, as shown by: http://ideone.com/ekWGg
Is this a bug in VC9 and if so, has this bug persisted into VC10?
I have however come up with a horrendously intrusive workaround (for this specific use case, at least. More general solutions welcome):
#include <boost/function_types/result_type.hpp>
#include <boost/type_traits/is_same.hpp>
template<typename F, typename R>
struct is_result_same :
boost::is_same<
typename boost::function_types::result_type<F>::type,
R
>
{};
template<class F, bool = is_result_same<F, void>::value>
struct special {};
template<class R, class C> struct special<R(C::*)(), true> {};
template<class R, class C> struct special<R(C::*)(), false> {};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个错误。
根据 14.5.4.2,这两个类模板特化的偏序与这些虚构函数模板的偏序相同:
根据 14.5.5.2,这两个函数模板的偏序是通过将发明的类型替换为每个函数模板来确定的。在一个函数模板的参数列表中键入模板参数,并尝试使用另一个函数模板中的该参数列表进行模板参数推导。
模板实参推导的详细信息参见14.8.2。有效的推导来自
template_name
和dependent_type1 (dependent_type2::*)(arg_list)
。所以f4(arg3())
推导成功,推导出f4(arg3());
。f3(arg4())
推导显然永远不会成功,因为void
和ty6
不统一。因此,函数模板 3 比函数模板 4 更专业。类模板专业化 1 比类模板专业化 2 更专业。因此,尽管
special
与两者都匹配专业化,它明确地实例化专业化 1。This is a bug.
According to 14.5.4.2, the partial ordering of these two class template specializations are the same as the partial ordering of these imaginary function templates:
According to 14.5.5.2, the partial ordering of these two function templates is determined by substituting invented types for each type template parameter in the argument list of one and attempting template argument deduction using that argument list in the other function template.
The details of template argument deduction are in 14.8.2. Among the valid deductions are from
template_name<dependent_type>
anddependent_type1 (dependent_type2::*)(arg_list)
. So thef4(arg3())
deduction succeeds, deducingf4<void,ty5>(arg3());
. Thef3(arg4())
deduction can obviously never succeed, sincevoid
andty6
do not unify.Therefore function template 3 is more specialized than function template 4. And class template specialization 1 is more specialized than class template specialization 2. So although
special<void(s::*)()>
matches both specializations, it unambiguously instantiates specialization 1.