成员函数模板选择和SFINAE [英] Member function template selection and SFINAE

查看:76
本文介绍了成员函数模板选择和SFINAE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图理解C ++选择模板的方式.即,请考虑以下代码示例:

I've been trying to understand the way C++ selects templates. Namely, consider the following code sample:

template <typename R>
class Curious
{
public:
    template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type = 33>
    void test1() {}

    template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type = 33>
    void test1() {}

    template <typename T, typename = typename std::enable_if<std::is_const<T>::value>::type>
    void test2() {}

    template <typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
    void test2() {}

    template <typename std::enable_if<std::is_const<R>::value>::type * = nullptr>
    void test3() {}

    template <typename std::enable_if<!std::is_const<R>::value>::type * = nullptr>
    void test3() {}

    // works
    template <typename T = void>
    typename std::enable_if<std::is_const<R>::value, T>::type test4() {}

    template <typename T = void>
    typename std::enable_if<!std::is_const<R>::value, T>::type test4() {}

    // also works
    template <typename T = void, typename std::enable_if<std::is_const<R>::value, T>::type * = nullptr>
    void test5() {}

    template <typename T = void, typename std::enable_if<!std::is_const<R>::value, T>::type * = nullptr>
    void test5() {}
}; // Curious

前两个功能(test1)工作正常(为什么?):

The first two functions (test1) work fine (why?):

Curious<int> curious;
curious.test1<int>();
curious.test1<const int>();

它们中的其余部分会导致编译错误.关于函数test2,编译器声称我正在尝试创建一个副本:

While the rest of them cause compilation errors. Regarding the function test2 the compiler claims I'm trying to create a duplicate:

error C2535: 'void Curious::test2(void)': member function already defined or declared

此处文档说:

一个常见的错误是声明两个仅不同的功能模板在其默认模板参数中.这是非法的,因为默认模板参数不是功能模板签名的一部分,并且声明两个具有相同签名的不同功能模板是非法的.

A common mistake is to declare two function templates that differ only in their default template arguments. This is illegal because default template arguments are not part of function template's signature, and declaring two different function templates with the same signature is illegal.

看来确实如此.但是,我发现与前两个函数没有什么太大区别,前两个函数也具有默认的模板参数.因此,对于默认值(test1-有效),我们有一个默认类型(test2-不起作用).有什么规定吗?

So it seems to be the case. However, I don't see that much difference from the first two functions, which also have the default template argument. Thus we have a default type (test2 - doesn't work) against a default value (test1 - works). Is there any rule about it?

如果是test3:

error C2039: 'type': is not a member of 'std::enable_if'

像这次的第一种情况一样,成员函数模板具有默认的非类型参数,但它取决于类模板参数.现在SFINAE不会跳过错误的错误(也不确定原因).

Like in the first case this time the member function template has a default non-type parameter, but it depends on the class template parameter. Now SFINAE doesn't skip the wrong one (also not sure why).

在第四种情况下,SFINEE通过返回类型解析模板.但是这些test4函数不具有相同的签名吗?因为它们仅在返回类型上有所不同.

In the fourth case SFINAE resolves the template by the return type. But don't these test4 functions have identical signature? As they differ only in the return type.

据我所知,在第五种情况下,添加额外的参数使test5签名依赖于功能模板参数,因此SFINAE起作用并且解析有效.

As far as I understand, in the fifth case adding extra parameter makes test5 signature dependent on the function template parameter, therefore SFINAE kicks in and resolution works.

我对C ++如何处理这些模板感到非常困惑.有人这么善良地清理掉这些东西吗?

I'm quite confused about how C++ deals with these templates. Could somebody be so kind to clear these things up?

推荐答案

  • 去掉默认值后,对于test1,您具有:

    • With default value removed, for test1, you have:

      template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type>
      void test1();
      
      template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type>
      void test1();
      

      签名明显不同.

      对于test2:

      template <typename T, typename> void test2();
      
      template <typename T, typename> void test2();
      

      显然是相同的签名.

      对于test3,SFINAE不适用,因为您遇到了严重错误,因为该类中已修复了 R ,并且您的 enable_if 不依赖于模板参数的功能.

      For test3, SFINAE doesn't apply as you have hard error as R is fixed in the class and your enable_if doesn't depend of template parameter of the function.

      对于test4,模板函数的签名存在一个例外,因为重载可能仅因返回类型而异

      For test4, there is an exception about signature for template function as overload may differ only by return type so

      int foo();
      char foo(); // Illegal.
      

      但是

      template <typename T> int foo();
      template <typename T> char foo(); // legal, even it is not trivial to call
      

      此外, std :: enable_if<!std :: is_const< R> :: value,T> :: type 取决于模板参数 T ,因此好的.

      In addition, std::enable_if<!std::is_const<R>::value, T>::type depends on template parameter T so it is ok.

      对于test5,第二个模板参数取决于第一个模板参数 T ,所以也可以.

      For test5, second template parameter depends on first template parameter T, so it is ok too.

      这篇关于成员函数模板选择和SFINAE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆