【问题标题】:Code using SFINAE working with GCC but not with Clang使用 SFINAE 与 GCC 但不与 Clang 一起使用的代码
【发布时间】:2016-07-19 18:08:50
【问题描述】:

我正在尝试在 C++11 中使用 SFINAE 来实现序列化库。我的代码适用于 GCC,但不适用于 Clang。我已将其简化为最少的代码:

template <typename A, typename T>
constexpr auto has_save_method(A& ar, T& t) -> decltype(t.save(ar), bool()) {
        return true;
}

template<class A, typename T, bool has_save>
struct saver;

template<class A, typename T>
struct saver<A,T,true> {
        static void apply(A& ar, T& t) {
                t.save(ar);
        }
};

class MyClass {

        public:

        template<typename A>
        void save(A& ar) {
                // Save the instance in the archive
        }
};

class MyArchive {};

template<typename A, typename T>
void save_to_archive(A& ar, T& t) {
        saver<A,T,has_save_method(ar,t)>::apply(ar,t);
}

int main(int argc, char** argv) {
        MyClass x;
        MyArchive a;
        save_to_archive(a,x);
        return 0;
}

GCC 编译它没有错误。然而,Clang 给了我以下信息:

test.cpp:30:28: error: non-type template argument is not a constant expression
         saver<A,T,has_save_method(ar,t)>::apply(ar,t);
                                   ^ 
test.cpp:36:2: note: in instantiation of function template specialization
       'save_to_archive<MyArchive, MyClass>' requested here
         save_to_archive(a,x);
         ^

发生了什么,我怎样才能使它与两个编译器一起工作?

【问题讨论】:

    标签: c++ c++11 g++ sfinae clang++


    【解决方案1】:

    这看起来像是 HERE 讨论的 Clang 问题

    另一种解决方案是使用void_t trick

    template <typename... T>
    using void_t = void;
    
    template <typename A, typename T, typename = void_t<>>
    struct has_save_method {
      constexpr static bool value = false;
    };
    
    template <typename A, typename T>
    struct has_save_method<A, T, void_t<decltype(std::declval<T&>().save(std::declval<A&>()))>> {
      constexpr static bool value = true;
    };
    

    并像这样使用它:

    template<typename A, typename T>
    void save_to_archive(A& ar, T& t) {
            saver<A,T,has_save_method<A, T>::value>::apply(ar,t);
    }
    

    【讨论】:

    • 我对 C++11 缺乏经验,无法理解问题本身,但您的解决方案有效;谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 2022-11-14
    • 2019-02-21
    相关资源
    最近更新 更多