std::enable_if 有条件地编译成员函数 [英] std::enable_if to conditionally compile a member function

查看:46
本文介绍了std::enable_if 有条件地编译成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过一个简单的例子来理解如何使用 std::enable_if.在我阅读了这个答案后,我认为应该不会太难举一个简单的例子.我想使用 std::enable_if 在两个成员函数之间进行选择,并且只允许使用其中一个.

I am trying to get a simple example to work to understand how to use std::enable_if. After I read this answer, I thought it shouldn't be too hard to come up with a simple example. I want to use std::enable_if to choose between two member-functions and allow only one of them to be used.

不幸的是,以下内容不能用 gcc 4.7 编译,经过数小时和数小时的尝试,我问你们我的错误是什么.

Unfortunately, the following doesn't compile with gcc 4.7 and after hours and hours of trying I am asking you guys what my mistake is.

#include <utility>
#include <iostream>

template< class T >
class Y {

    public:
        template < typename = typename std::enable_if< true >::type >
        T foo() {
            return 10;
        }
        template < typename = typename std::enable_if< false >::type >
        T foo() {
            return 10;
        }

};


int main() {
    Y< double > y;

    std::cout << y.foo() << std::endl;
}

gcc 报告以下问题:

gcc reports the following problems:

% LANG=C make CXXFLAGS="-std=c++0x" enable_if
g++ -std=c++0x    enable_if.cpp   -o enable_if
enable_if.cpp:12:65: error: `type' in `struct std::enable_if<false>' does not name a type
enable_if.cpp:13:15: error: `template<class T> template<class> T Y::foo()' cannot be overloaded
enable_if.cpp:9:15: error: with `template<class T> template<class> T Y::foo()'

为什么g++不删除第二个成员函数的错误实例化?根据标准,std::enable_if 仅当布尔模板参数为真时才存在.但是为什么 g++ 不认为这是 SFINAE 呢?我认为重载错误信息来自g++没有删除第二个成员函数的问题,认为这应该是重载.

Why doesn't g++ delete the wrong instantiation for the second member function? According to the standard, std::enable_if< bool, T = void >::type only exists when the boolean template parameter is true. But why doesn't g++ consider this as SFINAE? I think that the overloading error message comes from the problem that g++ doesn't delete the second member function and believes that this should be an overload.

推荐答案

SFINAE 仅在模板参数的参数推导中的替换使构造格式错误时才有效.没有这样的替代.

SFINAE only works if substitution in argument deduction of a template argument makes the construct ill-formed. There is no such substitution.

我也想到了这一点,并尝试使用 std::is_same<T, int >::value!std::is_same 给出相同的结果.

I thought of that too and tried to use std::is_same< T, int >::value and ! std::is_same< T, int >::value which gives the same result.

这是因为当类模板被实例化时(当你创建一个 Y 类型的对象时会发生这种情况),它会实例化它的所有成员声明(不一定是它们的定义/主体!).其中还有它的成员模板.请注意,T 是已知的,并且 !std::is_same<;T, int >::value 产生错误.所以它会创建一个类 Y ,其中包含

That's because when the class template is instantiated (which happens when you create an object of type Y<int> among other cases), it instantiates all its member declarations (not necessarily their definitions/bodies!). Among them are also its member templates. Note that T is known then, and !std::is_same< T, int >::value yields false. So it will create a class Y<int> which contains

class Y<int> {
    public:
        /* instantiated from
        template < typename = typename std::enable_if< 
          std::is_same< T, int >::value >::type >
        T foo() {
            return 10;
        }
        */

        template < typename = typename std::enable_if< true >::type >
        int foo();

        /* instantiated from

        template < typename = typename std::enable_if< 
          ! std::is_same< T, int >::value >::type >
        T foo() {
            return 10;
        }
        */

        template < typename = typename std::enable_if< false >::type >
        int foo();
};

std::enable_if::type 访问不存在的类型,因此该声明格式错误.因此您的程序无效.

The std::enable_if<false>::type accesses a non-existing type, so that declaration is ill-formed. And thus your program is invalid.

您需要使成员模板的 enable_if 依赖于成员模板本身的参数.然后声明是有效的,因为整个类型仍然是依赖的.当您尝试调用其中之一时,会对其模板参数进行参数推导,并且 SFINAE 会按预期进行.见 这个问题以及有关如何做到这一点的相应答案.

You need to make the member templates' enable_if depend on a parameter of the member template itself. Then the declarations are valid, because the whole type is still dependent. When you try to call one of them, argument deduction for their template arguments happen and SFINAE happens as expected. See this question and the corresponding answer on how to do that.

这篇关于std::enable_if 有条件地编译成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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