c++ - std::enable_if 有条件地编译一个成员函数

标签 c++ templates g++ c++11

我试图通过一个简单的示例来理解如何使用 std::enable_if .我读完this answer ,我认为想出一个简单的例子应该不会太难。我想用 std::enable_if在两个成员函数之间进行选择,并只允许使用其中一个。

不幸的是,以下代码无法使用 gcc 4.7 进行编译,经过数小时的尝试,我想问问你们我的错误是什么。

#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 报告以下问题:

% 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< bool, T = void >::type仅当 bool 模板参数为真时才存在。但为什么 g++ 不将其视为 SFINAE?我认为重载错误信息来自g++没有删除第二个成员函数的问题,认为这应该是一个重载。

最佳答案

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

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<int> 的对象时会发生这种情况),它会实例化其所有成员声明(不一定是它们的定义/主体!)。其中还有它的成员模板。注意 T然后是已知的,并且!std::is_same< T, int >::value产生错误。所以它会创建一个类 Y<int>其中包含

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<false>::type访问不存在的类型,因此该声明格式错误。因此您的程序无效。

您需要制作成员模板' enable_if取决于成员模板本身的参数。那么声明是有效的,因为整个类型仍然是依赖的。当您尝试调用其中之一时,会发生其模板参数的参数推导,并且 SFINAE 会按预期发生。参见 this question以及如何做到这一点的相应答案。

关于c++ - std::enable_if 有条件地编译一个成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41222414/

相关文章:

c++ - 误导性编译器错误消息 : size_t is not a member of std?

c++ - operator void*() 转换仍然是 C++ 库的一部分吗?

c++ - 没有全局变量初始化

c++ - GTest 的 EXPECT_EQ 给出未定义的错误引用

c++ - 初学者 C++ 程序中的分数组件

c++ - 如何在继承类成员函数中访问基类成员的地址?

c++ - 引用传递以错误结束

c++ - 缺少作用域变量 OpenCV c++

c++ - 为什么我无法构建此正则表达式

c++ - 如何使用父目录中的文件进行命令行编译?