c++ - Variadic 模板模拟 "runtime"扩展

标签 c++ templates variadic-templates

我有一个函数,我正在尝试将其转换为使用可变参数模板。不幸的是,在编译期间尝试对函数进行强类型化时,模板扩展会导致问题。

这是旧代码:

std::unique_ptr<std::stringstream> Execute(CommandType command, ...) {
    auto resp = std::make_unique<std::stringstream>();

    va_list vl;
    va_start(vl, command);

    switch(command) {
    case CommandType::Post:
        *resp << Post(va_arg(vl, char *), va_arg(vl, char *));
        break;
    case CommandType::Get:
        *resp << Get(va_arg(vl, char *));
        break;
    case CommandType::Delete:
        *resp << Delete(va_arg(vl, char *), va_arg(vl, char *));
        break;
    }
    va_end(vl);
    return resp;
}

以及对应的函数:

bool Post(char *command, char *payload);
char *Get(char *command);
bool Delete(char *command, char *name);

理想情况下,我希望能够将其转换为类似以下内容的内容:

template< typename... Params>
std::unique_ptr<stringstream> Execute(CommandType command, Params... parameters) {
    auto response = std::make_unique<stringstream>();
    if(command == CommandType::Get)
        response << Get(parameters);
    else if(command == CommandType::Post)
        response << Post(parameters);
    else if(command == CommandType::Delete)
        response << Delete(parameters);
    else if(command == CommandType::OtherFunc)
        response << OtherFunc(parameters);

    return response;
};

bool Post(std::string command, std::string payload);
std:string Get(std::string command);
bool Delete(std::string command, std::string name);
int OtherFunc(std::string command, bool enabled, MyClass name);
  • OtherFunc 添加到此处用于更复杂的类型示例。

但显然这行不通,因为编译器认为每个命令都应该将参数传递给模板,而实际上只有一个基于 CommandType 的命令应该接收参数。

有什么技巧可以使用模板重写它并保持强类型,或者我是否必须使用 var args 和指针来保留它?

最佳答案

您可以添加虚拟函数,例如:

template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
Post (Ts&&...) {return 0;}

template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
Delete (Ts&&...) {return 0;}

template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 3, int>::type
OtherFunc (Ts&&...) {return 0;}

SFINAE 实际上更复杂(并且应该使用 std::is_convertible),目的是避免在不使用精确类型但使用可转换类型时使用模板函数。

Live example

为了更完整,带有 std::is_convertible 的额外版本

template<typename T>
typename std::enable_if<!std::is_convertible<T, std::string>::value, int>::type
Get (T&&...) {return 0;}

template<typename T1, typename T2>
typename std::enable_if<!std::is_convertible<T1, std::string>::value
    || !std::is_convertible<T2, std::string>::value,
    int>::type
Post (T1&&, T2&&) {return 0;}

template<typename T1, typename T2>
typename std::enable_if<!std::is_convertible<T1, std::string>::value
    || !std::is_convertible<T2, std::string>::value,
    int>::type
Delete (T1&&, T2&&) {return 0;}

Live example (请注意,我更改了 OtherFunc 以在没有额外内容的情况下产生错误)。

关于c++ - Variadic 模板模拟 "runtime"扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29159831/

相关文章:

c++ - 在 Xcode 中将 unsigned long 向下转换为需要 C++ 中的 int 的方法

c++ - 关于 C++ 中的移位运算符技巧?

c++ - C++ 模板类中的等效实例

c++ - 如何编写以可变参数作为模板参数的成员函数

c++ - 基类的单元测试一个好方法

c++ - 仅包含基类 header 时访问派生类

c++ - 使用 CRTP 时 clang++ 不接受使用模板模板参数

c++ - 不同类别的 vector

c++ - 直接访问可变参数模板类的终止情况有效,但便利类访问编译失败

c++ - 从传递给构造函数的参数类型推导可变成员类型