将不同类型的参数传递给函数模板

Dum*_*i B 12 c++ templates function

考虑这个模板:

template<typename t>
t add(t a, t b) {
    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

如何传递不同类型的参数,以便返回值为:

  • int如果两个参数都是类型int.

  • float如果其中一个参数是类型的float.

  • float如果两个参数都是类型float.

我也尝试过为模板设置多个参数:

template<typename t, typename c>
Run Code Online (Sandbox Code Playgroud)

使用它们作为函数参数,因此它们可以是不同的(t add(t a, c b))但是我无法解决的问题是如何根据返回类型更改函数类型(int,float,double等)?

was*_*ful 12

你想要的是std::common_type:

template<typename T0, typename T1>
typename std::common_type<T0, T1>::type add(T0 a, T1 b) {
    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

文件说明:

对于算术类型,可以将公共类型视为(可能是混合模式)算术表达式的类型,例如T0()+ T1()+ ... + Tn().

但是,正如在评论中指出的@ Jarod42,这只是一个观点,并且可能是错在某些情况下,例如:std::common_type<char, char>::typechar而算术表达式char() + char()的产量int.


更完整的实现可以明确地转换结果以消除上述情况中的可能警告:

template<typename T0, typename T1, typename R = std::common_type_t<T0, T1>>
R add(T0 a, T1 b) {
    return static_cast<R>(a+b);
}
Run Code Online (Sandbox Code Playgroud)

std::common_type默认情况下,此处用于返回类型,但由于它是模板参数,因此在使用该函数时可以指定其他类型(在更复杂的用例中可能有用):

char a = 1, b = 2;
add<decltype(a), decltype(b), int>(a, b);
Run Code Online (Sandbox Code Playgroud)

使用std::conditionalstd::is_same,@ Jarod42在评论中提出的更完整的解决方案允许将模板R作为第一个参数,并保持自动扣除ab:

template <typename R, typename T0, typename T1>
using ResType = std::conditional_t<
    std::is_same<void, R>::value,
    std::common_type_t<T0, T1>, // default
    R                           // R was explicitly specified: use it
>;

template <typename R = void, typename T0, typename T1>
ResType<R, T0, T1> add(T0 a, T1 b)
{
    return static_cast<ResType<R, T0, T1>>(a + b);
}
Run Code Online (Sandbox Code Playgroud)

用法:

char a = 1, b = 2;
add(a, b);       // returns char
add<int>(a, b);  // returns int
Run Code Online (Sandbox Code Playgroud)

  • 该注释具有误导性,因为`std :: common_type_t <char,char>`是`char`而``decltype('c'+'c')`是`int`. (5认同)

Pio*_*ycz 11

使用自动类型推导(从c ++ 14开始):

template<typename t, typename u>
    auto add(t a, u b) {
        return a+b;
    }
Run Code Online (Sandbox Code Playgroud)

  • 对C++ 11的修改就是将`auto add(ta,tb)`改为`auto add(ta,tb) - > decltype(a + b)`. (6认同)
  • 注意`char + char`导致`int`,而其他答案导致`char`. (2认同)

Sto*_*ica 6

在c ++ 11及更高版本中,您可以使用 std::common_type

template<typename T1, typename T2>
auto add(T1 a, T2 b) -> typename std::common_type<T1, T2>::type {
  return a + b;
}
Run Code Online (Sandbox Code Playgroud)

auto如同在Piotr的回答中一样,它将像积分促销一样发挥作用,与仅仅进行类型推演没有多大区别.但是,如果您尝试将自定义类型作为参数(例如std::complex类)传递,它将真正开始闪耀.


我宁愿保留标准所强加的整体推广类型,所以也许这应该包含在另一个特征中.

template<typename T1, typename T2>
class AdditionTraits {
  using common_t = typename std::common_type<T1, T2>::type;
  constexpr static bool is_char = std::is_same<common_t, char>::value;
public:
  using type = typename std::conditional<is_char, int, common_t>::type;
};

template<typename T1, typename T2>
auto add(T1 a, T2 b) -> typename AdditionTraits <T1, T2>::type {
  return a + b;
}
Run Code Online (Sandbox Code Playgroud)

可以看到它将chars 添加到int标准促销规则中.