为了账号安全,请及时绑定邮箱和手机立即绑定

Std:Enable_if可以有条件地编译成员函数

Std:Enable_if可以有条件地编译成员函数

C++
LEATH 2019-07-03 15:30:22
Std:Enable_if可以有条件地编译成员函数我试着用一个简单的例子来理解如何使用std::enable_if..在我读完之后这个答案我认为想出一个简单的例子应该不难。我想用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只有当布尔模板参数为真时才存在。但是为什么g+不认为这是SFINAE呢?我认为重载错误消息来自g+不删除第二个成员函数的问题,并认为这应该是过载
查看完整描述

3 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

SFINAE只有当替换在参数演绎中的模板参数使构造不正确时才有效。没有这样的替代。

我也是这么想的,我试着用std::is_same< T, int >::value! std::is_same< T, int >::value结果是一样的。

这是因为当类模板被实例化时(当您创建一个类型为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就会像预期的那样发生。看见这个问题以及如何做到这一点的相应答案。


查看完整回答
反对 回复 2019-07-03
?
DIEA

TA贡献1820条经验 获得超2个赞

我做了这个简短的例子,这也是有效的。

#include <iostream>#include <type_traits>class foo;class bar;template<class T>struct is_bar{
    template<class Q = T>
    typename std::enable_if<std::is_same<Q, bar>::value, bool>::type check()
    {
        return true;
    }

    template<class Q = T>
    typename std::enable_if<!std::is_same<Q, bar>::value, bool>::type check()
    {
        return false;
    }};int main(){
    is_bar<foo> foo_is_bar;
    is_bar<bar> bar_is_bar;
    if (!foo_is_bar.check() && bar_is_bar.check())
        std::cout << "It works!" << std::endl;

    return 0;}

如果你想让我详细解释的话。我认为这段代码或多或少是不言自明的,但我还是这样做了,所以我可能错了:)

你可以看到它的作用这里.


查看完整回答
反对 回复 2019-07-03
?
慕仙森

TA贡献1827条经验 获得超7个赞

对于那些正在寻找“只起作用”的解决方案的后来者来说:

#include <utility>#include <iostream>template< typename T >class Y {

    template< bool cond, typename U >
    using resolvedType  = typename std::enable_if< cond, U >::type; 

    public:
        template< typename U = T > 
        resolvedType< true, U > foo() {
            return 11;
        }
        template< typename U = T >
        resolvedType< false, U > foo() {
            return 12;
        }};int main() {
    Y< double > y;

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

汇编:

g++ -std=gnu++14 test.cpp

跑步给:

./a.out 
11


查看完整回答
反对 回复 2019-07-03
  • 3 回答
  • 0 关注
  • 1844 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信