转换可变参数函数的参数

Convert arguments of variadic function

这可能是一个新手问题,但我认为它可能很有趣。假设我有这个功能:

template <typename First, typename... T>
int ComputeSomething(const First& f, const T&... t);

我想编写第二个函数,在一般情况下调用上面的函数,但在 FirstT 的类型为 float 时转换参数,即,它在每个参数上调用一个 Convert 函数:

long Convert(float f);

template <typename First, typename... T>
int MyFun(const First& f, const T&... t) {
  return ComputeSomething(f, t...);
}

// This is what I would like:
int MyFun(const float& f, const float& t...) {
  return ComputeSomething(Convert(f), Convert(t)...);
}

我怎样才能做到这一点?

您可以使用助手来测试是否所有类型都是 float:

#include <type_traits>

template< typename... > struct typelist {};

template< typename T, typename... Ts >
using is_all_same = std::is_same< typelist< T, Ts... >,
                                  typelist< Ts..., T > >;

long Convert(float f);

template <typename First, typename... T>
typename std::enable_if< !is_all_same< float, First, T... >::value, int >::type
MyFun(const First& f, const T&... t) {
  return ComputeSomething(f, t...);
}

template <typename First, typename... T>
typename std::enable_if< is_all_same< float, First, T... >::value, int >::type
MyFun(const First& f, const T&... t) {
  return ComputeSomething(Convert(f), Convert(t)...);
}

助手非常通用,也可以在其他上下文中使用。

编辑:我将 std::tuple 替换为 typelist,尽管在上述上下文中永远不会实例化元组。我只是为了方便而使用它,但由于有些人认为它的开销太大,所以我编辑了答案。

添加一个透明的 Convert 重载,以便绕过非浮点数(也就是说,您可以使用混合类型的参数):

template <typename First, typename... T>
int ComputeSomething(const First& f, const T&... t);

long Convert(float f);

// Transparent converter
template <typename T>
T&& Convert(T&& t) { return std::forward<T>(t); }

template <typename First, typename... Ts>
int MyFun(const First& f, const Ts&... t)
{
    return ComputeSomething(Convert(f), Convert(t)...);
}

DEMO