c++ - SFINAE decltype 逗号运算符技巧

标签 c++ c++11 sfinae

阅读马蒂厄的回答后here ,我决定自己尝试一下。

我的尝试编译失败,因为 SFINAE 没有启动并剔除试图访问 T::foohas_foo 函数。

error: ‘struct Bar’ has no member named ‘foo’

我是否遗漏了什么,或者我试图以这种方式不可能做到的事情?

(我使用的是 gcc-4.7.2)

下面的完整示例:

#include <iostream>

// culled by SFINAE if foo does not exist
template<typename T>
constexpr auto has_foo(T& t) -> decltype((void)t.foo, bool())
{
    return true;
}
// catch-all fallback for items with no foo
constexpr bool has_foo(...)
{
    return false;
}
//-----------------------------------------------------

template<typename T, bool>
struct GetFoo
{
    static int value(T& t)
    {
        return t.foo;
    }
};
template<typename T>
struct GetFoo<T, false>
{
    static int value(T&)
    {
        return 0;
    }
};
//-----------------------------------------------------

template<typename T>
int get_foo(T& t)
{
    return GetFoo<T, has_foo(t)>::value(t);
}
//-----------------------------------------------------

struct Bar
{
    int val;
};

int main()
{
    Bar b { 5 };
    std::cout << get_foo(b) << std::endl;
    return 0;
}

最佳答案

AFAICS 的主要问题是您将 run-time 引用用作 constexpr 函数参数。替换它就可以了。

#include <iostream>

// culled by SFINAE if foo does not exist
template<typename T>
constexpr auto has_foo(int) -> decltype(std::declval<T>().foo, bool())
{
    return true;
}
// catch-all fallback for items with no foo
template<typename T> constexpr bool has_foo(...)
{
    return false;
}
//-----------------------------------------------------

template<typename T, bool>
struct GetFoo
{
    static int value(T& t)
    {
        return t.foo;
    }
};
template<typename T>
struct GetFoo<T, false>
{
    static int value(T&)
    {
        return 0;
    }
};
//-----------------------------------------------------

template<typename T>
int get_foo(T& t)
{
    return GetFoo<T, has_foo<T>(0)>::value(t);
}
//-----------------------------------------------------

struct Bar
{
    int val;
};
struct Foo {
    int foo;
};

int main()
{
    Bar b { 5 };
    Foo f { 5 };
    std::cout << get_foo(b) << std::endl;
    std::cout << get_foo(f) << std::endl;
    return 0;
}

关于c++ - SFINAE decltype 逗号运算符技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18265536/

相关文章:

c++ - 完善的转发功能推导出冲突错误

c++ - 检查函数模板是否是一元的

c++ - 检查类型 T 是否有成员函数 SFINAE 的任何重载

c++ - 条件 (SFINAE) 覆盖

java - 我怎样才能避免在 java 中做很多 if?

c++ - 将模板参数限制为仅具有不同构造函数签名的一组类

c++ - regex_search C++ 不匹配子字符串

c++ - 为什么我的派生类找不到我的基类的类型别名?

c++ - 为什么我们需要语法产生式基本说明符的最后两个定义?

c# - 是否可以有效地计算与数轴上的单个点 P 重叠的线段数?