提问者:小点点

C++模板宏


#define BINDINGTEMPLATE template<typename T, typename = typename std::enable_if_t < std::is_same_v<typename std::decay_t<T>, int> || std::is_same_v<typename std::decay_t<T>, std::string> || std::is_same_v<typename std::decay_t<T>, char>>>

像这样的做法是不是很糟糕? 我在同一个类内多次使用这个函数模板。

例如,我需要在许多函数中使用它,例如:

BINDINGTEMPLATE
void myFunction(int x, int y){
dosomething specialised based on input template
}

共3个答案

匿名用户

您也可以通过类型特征实现同样的目标:

template <typename T>
using enable_if_int_or_string_or_char = std::enable_if_t < 
                             std::is_same_v<typename std::decay_t<T>, int> 
                             || std::is_same_v<typename std::decay_t<T>, std::string> 
                             || std::is_same_v<typename std::decay_t<T>, char>>;

然后可以使用ENABLE_IF_INT_OR_STRING_OR_CHAR代替宏。 宏有严重的缺点,所以最好的宏是不需要使用的宏。

匿名用户

是的,这是个坏习惯。 不要将宏用于没有宏就可以轻松完成的事情。

您可以将长SFINAE条件转换为

template <typename T> using foo = std::enable_if_t<...>;

然后你可以简单地写:

template <typename T, typename = foo<T>>
void myFunction(int x, int y)

或者,您可以将条件放入constexpr函数或变量模板中,然后在每次使用它时编写enable_if_t

您还可以使用一个概念(需要C++20):

template <typename T>
concept foo = std::is_same_v<typename std::decay_t<T>, int> || etc;

template <foo T>
void myFunction(int x, int y)

请注意,使用enable_if_t(无论您是否使用帮助器使用)并不是非常健壮,因为用户可以通过显式指定第二个模板参数来规避它。

更好的办法是:

template <typename T, std::enable_if_t<..., std::nullptr_t> = nullptr>
void myFunction(int x, int y)

除了万无一失之外,这还允许您根据不同的特性来过载函数。

这些概念也解决了这两个问题。

匿名用户

IMHO,宏是蒸馏出来的邪恶。

所以,是的:(IMHO)是不好的做法。

我提出另一种方法(只是为了好玩:其他答案显示了很好的解决方案)来避免它。

您可以声明一个foo()(SFINAE启用/禁用函数),如下所示

template <typename T>
std::enable_if_t<std::is_same_v<std::decay_t<T>, int>
              || std::is_same_v<std::decay_t<T>, std::string>
              || std::is_same_v<std::decay_t<T>, char>> foo ();

您可以使用它来编写您的最终函数

template <typename T>
decltype(foo<T>()) bar (int, int)
 { }

下面是一个完整的编译示例

#include <string>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_same_v<std::decay_t<T>, int>
              || std::is_same_v<std::decay_t<T>, std::string>
              || std::is_same_v<std::decay_t<T>, char>> foo ();

template <typename T>
decltype(foo<T>()) bar (int, int)
 { }

int main ()
 { 
   bar<int>(0, 0);     // compile
   // bar<long>(0, 0); // compilation error
 }

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|模板|宏)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?