代码之家  ›  专栏  ›  技术社区  ›  tangy

具有模板化类成员函数的sfinae

  •  0
  • tangy  · 技术社区  · 7 年前

    我正在尝试学习sfinae,在尝试将其应用于模板类成员函数时遇到了一个问题。多亏了 Why doesn't SFINAE (enable_if) work for member functions of a class template? 我能够建立一个基本的例子( Run online ):

    template<typename T>
    class Foo{
        public:
        template <typename U = T, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int> = 0>
        void sfinae() { // Foo<anything else>
            std::cout << "sfinae default" << std::endl;
        }
    
        template <typename U = T, typename std::enable_if_t<std::is_same<U, int>::value,int> = 0>
        void sfinae() { // Foo<int>
            std::cout << "sfinae int" << std::endl;
        }
    
        template <typename U = T, typename std::enable_if_t<std::is_same<U, float>::value,int> = 0>
        void sfinae() { // Foo<float>
            std::cout << "sfinae float" << std::endl;
        }
    };
    

    我有两个后续问题:
    1。 如何分离成员函数的声明和定义?
    我尝试了如下定义:

    template <typename T>
    template <typename U = T, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int> = 0>
        void Foo<T>::sfinae() { // Foo<anything else>
            std::cout << "sfinae default" << std::endl;
        }
    

    但这会导致编译错误。

    2。catch all默认情况(打印sfinae默认值)当前必须写入为 not(type1, type2,...) 这可能是巨大的。是否有更短/更干净的解决方案?

    编辑 : 根据@jans的回答,这里是 corrected solution .

    1 回复  |  直到 7 年前
        1
  •  1
  •   Jans    7 年前

    脱线 定义删除默认参数,这些参数取自声明:

    template <class T>
    template <typename U, typename std::enable_if_t<!std::is_same<U, int>::value && !std::is_same<U, float>::value,int>>
    void Foo<T>::sfinae() { // Foo<anything else>
        std::cout << "sfinae default" << std::endl;
    }
    

    其他的也一样

    catch all默认情况(打印sfinae默认值)当前必须写入为 not(type1, type2,...) 这可能是巨大的。是否有更短/更干净的解决方案?

    为此,需要添加一个额外的参数来对为catch all提供最低排名的重载进行排名,这通常是使用省略号参数不优于任何其他参数类型的事实来完成的:

    template <typename U = T>
    void sfinae(...);
    
    template <typename U = T, typename std::enable_if_t<std::is_same<U, int>::value,int> = 0>
    void sfinae(int);
    
    template <typename U = T, typename std::enable_if_t<std::is_same<U, float>::value,int> = 0>
    void sfinae(int);
    
    Foo<char>{}.sfinae(0); // select the catch-all
    

    这意味着自从 ... 比任何其他参数都差( int 比…好 )过载 sfinae(...) 只有当其他两个不能被调用时才被考虑,也就是说,如果它们是sfinae。