简体   繁体   English

在成员函数返回类型上参数化的类模板部分特化

[英]class template partial specialization parametrized on member function return type

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: 以下代码尝试根据成员函数指针类型的返回类型来专门化类模板'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;
}

error C2752: 'special' : more than one partial specialization matches the template argument list 错误C2752:'special':多个部分特化匹配模板参数列表

The same code is accepted by GCC-4.3.4, as shown by: http://ideone.com/ekWGg GCC-4.3.4接受相同的代码,如: http//ideone.com/ekWGg所示
Is this a bug in VC9 and if so, has this bug persisted into VC10? 这是VC9中的一个错误,如果是这样,这个错误是否一直存在于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> {};

This is a bug. 这是一个错误。

template <class C> struct special<void(C::*)()>;        // specialization 1
template <class R, class C> struct special<R(C::*)()>;  // specialization 2

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: 根据14.5.4.2,这两个类模板特化的部分排序与这些虚函数模板的部分排序相同:

template <class C> void f(special<void(C::*)()>);       // func-template 3
template <class R, class C> void f(special<R(C::*)()>); // func-template 4

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. 根据14.5.5.2,这两个函数模板的部分排序是通过在一个参数列表中用每个类型模板参数替换发明类型并在另一个函数模板中使用该参数列表尝试模板参数推导来确定的。

// Rewrite the function templates with different names -
// template argument deduction does not involve overload resolution.
template <class C> void f3(special<void(C::*)()>);
template <class R, class C> void f4(special<R(C::*)()>);

struct ty5 {}; struct ty6 {}; struct ty7 {};
typedef special<void(ty5::*)()> arg3;
typedef special<ty6 (ty7::*)()> arg4;

  // compiler internally tests whether these are well-formed and
  // the resulting parameter conversion sequences are "exact":
  f3(arg4());
  f4(arg3());

The details of template argument deduction are in 14.8.2. 模板参数推导的细节见14.8.2。 Among the valid deductions are from template_name<dependent_type> and dependent_type1 (dependent_type2::*)(arg_list) . 有效推论包括template_name<dependent_type>dependent_type1 (dependent_type2::*)(arg_list) So the f4(arg3()) deduction succeeds, deducing f4<void,ty5>(arg3()); 所以f4(arg3())推论成功,推导出f4<void,ty5>(arg3()); . The f3(arg4()) deduction can obviously never succeed, since void and ty6 do not unify. f3(arg4())推论显然永远不会成功,因为voidty6没有统一。

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. 因此,函数模板3比函数模板4更专业。类模板特化1比类模板special<void(s::*)()> 2更专业。因此虽然special<void(s::*)()>匹配两个特化,但它明确地实例化了特化1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM