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

发布于 2024-10-19 03:18:50 字数 1142 浏览 4 评论 0原文

以下代码尝试根据成员函数指针类型的返回类型对类模板“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

锦上情书 2024-10-26 03:18:50

这是一个错误。

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

根据 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

根据 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());

模板实参推导的详细信息参见14.8.2。有效的推导来自 template_namedependent_type1 (dependent_type2::*)(arg_list)。所以f4(arg3())推导成功,推导出f4(arg3());f3(arg4()) 推导显然永远不会成功,因为 voidty6 不统一。

因此,函数模板 3 比函数模板 4 更专业。类模板专业化 1 比类模板专业化 2 更专业。因此,尽管 special 与两者都匹配专业化,它明确地实例化专业化 1。

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:

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.

// 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. Among the valid deductions are from template_name<dependent_type> and dependent_type1 (dependent_type2::*)(arg_list). So the f4(arg3()) deduction succeeds, deducing f4<void,ty5>(arg3());. The f3(arg4()) deduction can obviously never succeed, since void and ty6 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文