c++ 模板重载方法取决于 class 类型

c++ templates overloading method depend on class type

我有 class 这样的:

template<typename T>
MyClass{
   //myFunc();
}

我想创建 myFunc 方法,如果 class 模板是数字,则 return 数值,当 class 模板不是数字时,return 什么都没有(无效)。

现在,我得到了这样的东西:

template<typename T>
MyClass{
   template <typename returnT>
   returnT myFunc();
}


template <typename T>
template <typename returnT>
typename std::enable_if<std::is_arithmetic<T>::value>
T MyClass<T>::myFunc()
{
    return T::value;
}

template <typename T>
template <typename returnT>
typename std::enable_if<!std::is_arithmetic<T>::value>
void MyClass::myFunc()
{
    //do sth
}

当然,那是行不通的。以这种方式解决这个问题是个好主意吗?什么是 "smart" 和可行的解决方案?

我能想到的最简单的方法就是使用 if constexpr:

template <typename T>
class MyClass
{
    auto myFunc()
    {
        if constexpr (std::is_arithmetic_v<T>)
        {
            return T{};
        }
        else
        {
            // do smth
        }
    }
};

如果你不能使用 C++17,你将不得不恢复到一些基于 SFINAE 的方法。最好的样子在很大程度上取决于所涉及的实际签名应该是什么。但是,例如,您可以为算术类型的情况提供部分 class 模板特化:

template <typename T, typename = void>
class MyClass
{
    void myFunc()
    {
        // do smth
    }
};

template <typename T>
class MyClass<T, std::enable_if_t<std::is_arithmetic<T>::value>>
{
    T myFunc()
    {
        return {};
    }
};

请注意算术类型不能是 class 类型或枚举,所以我不确定 T::value 在您的示例代码中针对 [=14= 的情况试图实现什么] 算术类型…

作为已提供的 constexpr if 解决方案的替代方案,这里是您的初步想法的工作形式。

#include <type_traits>
#include <iostream>

template<typename T>
struct MyClass{
   template <typename returnT = T, std::enable_if_t<std::is_arithmetic_v<returnT>, bool> = true>
   T myFunc();

   template <typename returnT = T, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool> = true>
   void myFunc();
};


template <typename T>
template <typename returnT, std::enable_if_t<std::is_arithmetic_v<returnT>, bool>>
T MyClass<T>::myFunc()
{
    std::cout << "yo\n";
    return T{};
}

template <typename T>
template <typename returnT, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool>>
void MyClass<T>::myFunc()
{
    std::cout << "yay\n";
}

int main() {
    MyClass<int> m;
    MyClass<std::string> n;
    m.myFunc();
    n.myFunc();
}

我会创建一个辅助模板 class 到 select return 类型,以及一个使用重载来执行正确行为的辅助函数。

template <typename, bool> struct RType;
template <typename T> struct RType<T, false> { typedef void type; };
template <typename T> struct RType<T, true> { typedef T type; };

template<typename T>
class MyClass{
    typedef RType<T, std::is_arithmetic<T>::value> R;

    void myFuncT(RType<T, false>) {}
    T myFuncT(RType<T, true>) { return 0; }

public:
    typename R::type myFunc() { return myFuncT(R()); }
};