是否有一种方法可以在基于枚举的可变参数模板函数之间进行选择,这比在结构中包装函数更简单?

时间:2018-01-08 16:56:35

标签: c++ variadic-templates

目前的代码如下:

// 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类型的工厂函数。

2 个答案:

答案 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;
    }
}

Demo