使用SFINAE给出了GCC和Clang的不同结果(Using SFINAE gives diffe

2019-09-19 20:24发布

我正在学习如何使用SFINAE我的优势。 我试图用它来选择一个基于存在的功能实现serialize()中的对象的功能。

这是我使用,以确定,如果类型定义了序列化()函数的代码:

template <typename T>
class HasSerialize {
    private:
        typedef char yes[1];
        typedef char no[2];

        template <typename C> static yes& test(char[sizeof(&C::serialize)]) ;
        template <typename C> static no& test(...);
    public:
        static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

然而,这似乎给出GCC和准确锵结果oposite。 假设下面的代码:

template<bool T>
class NVPtypeSerializer {
    public:
        template<typename C>
        static xmlChar* serialize(C value) {
            // serize() is not available
        }
};

template<>
struct NVPtypeSerializer<true> {
    public:
        template<typename T>
        static xmlChar* serialize(T value) {
            return value.serialize();
        }
};

这被称为是这样的:

foo = NVPtypeSerializer<HasSerialize<Bar>::value >::serialize(value);

凡类Bar没有serialize()函数。 此代码锵3.1下编译正常,但是在GCC 4.7.1,我得到以下错误:

error: ‘class Bar’ has no member named ‘serialize’

如果我改变了struct NVPtypeSerializer<true> ,以struct NVPtypeSerializer<false>可以在GCC编译,但是锵提供了以下错误:

error: no member named 'serialize' in 'Bar'

问题出在哪儿? 它是在我的代码? 我想有代码便携尽可能。

Answer 1:

这是真正的代码test(char[sizeof(&C::serialize)]) 需要注意的是,实际上需要一个数组的函数的声明声明一个函数,指针:

template <typename C> static yes& test(char[sizeof(&C::serialize)]) ;

这实际上意味着:

template <typename C> static yes& test( char* );

这亦是什么使您的通话test<C>(0)编译。 我不认为是检测功能是否存在或不正确的方法。 谷歌如何检测是否使用SFINAE在一个类中存在一个成员/成员函数。

(一个简单的解决办法是增加一个额外的违约参数--provided你有一个C ++ 11启用编译:

template <typename C, std::size_t = sizeof(&C::serialize)> 
static yes& test(int) ;



文章来源: Using SFINAE gives different results on GCC and Clang