SFINAE decltype comma operator trick

让人想犯罪 __ 提交于 2019-12-31 21:09:11

问题


After reading Matthieu's answer here, I decided to try this myself.

My attempt fails to compile because SFINAE doesn't kick in and cull the has_foo function which attempts to access T::foo.

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

Am I missing something, or is what I'm attempting to do not possible in this way?

(I'm using gcc-4.7.2)

Full examplar below:

#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;
}

回答1:


The primary issue here AFAICS is that you are using the run-time reference as a constexpr function parameter. Replacing this works just fine.

#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;
}


来源:https://stackoverflow.com/questions/18265536/sfinae-decltype-comma-operator-trick

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!