函数是否可以仅接受给定参数的有限类型集?

rsk*_*k82 4 c++ polymorphism templates function c++11

我知道如何使用模板的任何数据类型:

template<typename T>
T myFunc(T data) { ... }
Run Code Online (Sandbox Code Playgroud)

但是,有没有办法设定的允许的类型缩小到例如intcharstd::stringstd::wstring,所以编译器将抛出一个错误,遇到不允许参数类型的时候,我会得到编译时间,而不是运行时错误?

编辑:非常感谢ecatmur,现在我理解了整个概念.

template<typename itemA_type, typename itemB_type>
typename std::enable_if<
  (
    std::is_same<itemA_type, int>::value ||
    std::is_same<itemA_type, char>::value) &&
  (
    std::is_same<itemB_type, std::string>::value ||
    std::is_same<itemB_type, std::wstring>::value ||
    std::is_same<itemB_type, const char*>::value ||
    std::is_same<itemB_type, const wchar_t*>::value
  ) ,
  void
>::type
myFunction(itemA_type itemA, itemB_type itemB) {
  using namespace std;
  cout << itemA << itemB << endl;
}
Run Code Online (Sandbox Code Playgroud)

jro*_*rok 10

拿这个实用程序特质类:

template<typename T, typename U, typename... Us>
struct is_any_of
    : std::integral_constant<
        bool,
        std::conditional<
            std::is_same<T,U>::value,
            std::true_type,
            is_any_of<T,Us...>
        >::type::value
      >
{ };

template<typename T, typename U>
struct is_any_of<T,U> : std::is_same<T,U>::type { };
Run Code Online (Sandbox Code Playgroud)

然后你可以在静态断言中使用它:

template<typename T>
T myFunc(T data)
{
    static_assert( is_any_of<T, int, char, std::string>{}, "T not allowed");
}
Run Code Online (Sandbox Code Playgroud)

如果您觉得更合适,可以使用std::is_convertiblestd::is_constructible代替std::is_same.

实例.


Max*_*kin 5

你可以使用 SFINAE 做到这一点:

#include <type_traits>

template<class T> struct AllowedType : std::false_type {};
template<> struct AllowedType<int> : std::true_type {}; // Add more specializations.
template<> struct AllowedType<char> : std::true_type {}; // Add more specializations.

template<typename T>
typename std::enable_if<AllowedType<T>::value, T>::type
myFunc(T data);

int main() {
    myFunc(1);   // int, okay
    myFunc('c'); // char, okay
    myFunc(1.);  // double, fail
}
Run Code Online (Sandbox Code Playgroud)

或者您可以将允许的类型集指定为boost::mpl::vector<>序列(与上述效果相同):

#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/utility/enable_if.hpp>

typedef boost::mpl::vector<int, char> allowed_type_set;

template<typename T>
typename boost::enable_if<boost::mpl::contains<allowed_type_set, T>, T>::type
myFunc(T data);

int main() {
    myFunc(1);   // int, okay
    myFunc('c'); // char, okay
    myFunc(1.);  // double, fail
}
Run Code Online (Sandbox Code Playgroud)


eca*_*mur 5

使用enable_if和的简单解决方案is_same:

template<typename T>
typename std::enable_if<
    std::is_same<T, int>::value ||
    std::is_same<T, char>::value,
    T>::type
myFunc(T data) { ... }
Run Code Online (Sandbox Code Playgroud)

随着谓词T变得越来越复杂(例如,你只是允许stringwstring/或其他特化basic_string?)你可能开始想要编写更复杂的谓词元函数; 但就目前而言,一个简单的表达可能就足够了.