目前的代码如下:
// header file...
enum class FuncType {
AddTwoInts,
SquareAnInt
};
template<FuncType F, typename... Ts>
int getValue(Ts...);
// ----------------------------------------
// cpp file...
template<FuncType F>
struct FuncHelper;
template<>
struct FuncHelper<FuncType::AddTwoInts> {
static int func(int v1, int v2) {return v1 + v2;}
}
template<>
struct FuncHelper<FuncType::SquareAnInt> {
static int func(int v) { return v*v; }
}
template <FuncType F, typename... Ts>
int getValue(Ts... args) {
return FuncHelper<F>::func(args...);
}
// explicitly instantiate versions of getValue for each FuncType
// with the correct args...
template int getValue<FuncType::AddTwoInts, int, int>(int , int);
template int getValue<FuncType::SquareAnInt, int>(int)
以上内容可以通过包含标题然后调用
来使用auto val = getValue<FuncType::AddTwoInts>( 3, 4 );
这是我想要的确切界面,但是想要执行实现而无需使用FuncHelper或类似的东西。有没有办法在编译时更直接地选择可变参数模板?
上面我也没有看到任何问题吗?我上面的实际用例是作为一些数据+ std :: function的struct类型的工厂函数。
答案 0 :(得分:1)
如果您只是想避开结构,可以使用SFINAE执行此操作。
#include <type_traits>
enum class FuncType {
AddTwoInts,
MulTwoInts,
SquareAnInt,
ReturnAnInt
};
template<FuncType F, typename... Ts>
int getValue(Ts...);
// ----------------------------------------
// cpp file...
template<FuncType F, typename std::enable_if<F == FuncType::AddTwoInts, int>::type D>
int getValue_aux(int v1, int v2) { return v1 + v2; }
template<FuncType F, typename std::enable_if<F == FuncType::MulTwoInts, int>::type D>
int getValue_aux(int v1, int v2) { return v1 * v2; }
template<FuncType F, typename std::enable_if<F == FuncType::SquareAnInt, int>::type D>
int getValue_aux(int v) { return v * v; }
template<FuncType F, typename std::enable_if<F == FuncType::ReturnAnInt, int>::type D>
int getValue_aux(int v) { return v; }
template<FuncType F, typename... Ts>
int getValue(Ts... args)
{
return getValue_aux<F, 0>(args...);
}
在没有辅助功能的情况下在内部进行多个实现是不可能的,因为它们具有不同的arity(因此您需要在某处解压缩可变参数)。如果您的所有impl都具有相同的参数列表(或者如果可能的参数列表数量相对较少),您可以switch
上的FuncType
并让优化器完成选择正确的工作一个在编译时。
答案 1 :(得分:1)
在C ++ 17中,您可以这样做:
template<FuncType F, typename... Ts>
int getValue(Ts...args)
{
if constexpr (F == FuncType::AddTwoInts) {
static_assert(sizeof...(Ts) == 2, "!");
return (args + ...);
} else {
static_assert(sizeof...(Ts) == 1, "!");
const auto& first = std::get<0>(std::tie(args...));
return first * first;
}
}