首页 > 解决方案 > 允许模板参数仅是某些类型并根据它决定操作

问题描述

假设我有两节课MyClass_oneMyClass_two

我有只接受它们作为第一个参数的函数

template<typename T,typename ...Ts>
void doSomething(T one, Ts...two){}

现在为了简单起见,如果参数oneMyClass_one它应该打印“im one”,如果MyClass_two它应该打印“im two”。

如何真正实现这一目标?我想出的唯一解决方案真的很丑,并且不包含编译错误抛出:

template<typename T> isOne{ static const bool value = false}
template<> isOne<MyClass_one>{ static const bool value = true}

template<typename T> isTwo{ static const bool value = false}
template<> isTwo<MyClass_two>{ static const bool value = true}

template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
  if( isOne<T>::value ) { cout << "im one" << endl;}
  else if ( isTwo<T>::value){ cout <<"im two" << endl;}
}

然而,如何在不重载(函数的多个定义)的情况下实现编译器错误检查,例如,如果传递了ordoSomething()之外的其他内容,则该函数将无法编译。MyClass_oneMyClass_two

感谢帮助。

标签: c++templates

解决方案


如果你可以使用 C++17,你可以使用if constexpr

template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
  if constexpr ( isOne<T>::value ) { cout << "im one" << endl;}
  else if constexpr ( isTwo<T>::value){ cout <<"im two" << endl;}
}

当然,isOne<T>::value并且isTwo<T>::value需要是static constexpr变量。

如果你想检查第一个函数参数的类型,同样的方法也成立,只是不需要像isOneand之类的东西isTwo,你可以用它std::is_same_v来查看第一个参数是MyClassOneor MyClassTwo

#include <iostream> 
#include <type_traits>
#include <vector> 

class MyClassOne {}; 
class MyClassTwo {}; 

template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
  if constexpr ( std::is_same_v<T, MyClassOne> ) 
    std::cout << "im one" << std::endl;
  else if constexpr ( std::is_same_v<T, MyClassTwo> )
    std::cout <<"im two" << std::endl;
  else
    static_assert(false, "Only MyClassOne and MyClassTwo are permitted first arguments.");
}
int                                                                                                                                         
main(int argc, char **argv) { 

    MyClassOne one; 
    MyClassTwo two; 

    doSomething(one, 1.5, two); 
    doSomething(two, 'c', one);

    std::vector<MyClassOne> onesVector;
    doSomething(onesVector, 1.0); 

}  

std::is_same_v<A,B>true如果类型AB相同,则产生一个值。这回答了您的问题“如果参数一个是 MyClass_one,它应该打印“im one”,如果它的 MyClass_two 它应该打印“im two”。”,并且如果第一个参数是任何不同于 etithermyClassOne或的类型,则在编译时失败myClassTwo

编辑:添加了一个,如果第一个参数是除orstatic_assert之外的任何其他内容,则确保编译失败,正如 Justin Time 在评论中所建议的那样。MyClassOneMyClassTwo


推荐阅读