将C数组转换为可变参数模板参数

时间:2019-02-27 19:27:36

标签: c++ templates

我一直在探索CPP,并想知道是否有可能这样做:

可变参数模板类,它将N个元素的数组转换为带有可变参数列表的函数调用。

例如,如果给定这样的数组

argc = 3, args = { "hello", "10", "0.5" }

我希望能够这样打电话

Something<std::string, int, float>(3, args);

这将进行一些处理以使用转换后的参数调用函数

我探索过的先前资源试图使用C ++ 14的表达式折叠或试图使用递归模板。我认为必须使用参数包和一些定义来转换它。到目前为止,这是我的代码

假设要将C字符串数组转换为参数,我创建了许多转换结构

在这里,我有一个将char *(数组的元素)转换为未知参数的结构

// generic conversion
template <typename T>
struct convert {
  T operator()(char const*) const;
};

// specific convert char* to std::string
template <>
struct convert<std::string> {
  std::string operator()(char const* str) const {
    return std::string(str);
  }
};

// many different convert<> structs for different types...

现在是问题所在。在本课中,我尝试构建C字符串的N个元素的任意转换器的表示形式

class Handler {
public:
  virtual bool Handle(int argc, char const** argv);
};

template <typename... Args>
class Command : public Handler {
protected:
  bool Execute(Args... args);

public:
  bool Handle(int argc, char const** argv) override {
    if (argc != sizeof...(Args))
      return false;
    // HELP call convert<> on each type in args then call Execute();
  }
};

对于我的HELP,我探索了另一个问题来尝试参数解压缩或表达式折叠,但是不喜欢他。

例如,命令的一种实现是

class Help : public Command<std::string> {
public:
  bool Execute(std::string sub) {

  }
};

我也尝试使用CPP14索引序列,但是我的问题是要在索引序列中有两个“数组”进行迭代。 char **和可变参数模板。

谢谢!

1 个答案:

答案 0 :(得分:0)

使用可变参数模板,您可以有多个包以一种模式扩展。

您可以使用它来获取args数组的索引和参数包中的类型。

这是解决方案:

#include <type_traits>
#include <utility>
#include <string>

template<typename T>
struct Convert {
    auto operator()(char const*) -> T {
        return T{};
    }
};

template<typename... Args>
struct Command {
    bool execute(Args...) {
        return true;
    }

    bool handle(int argc, char const** args) {
        // This should be a precondition
        if (argc != sizeof...(Args)) { 
            return false;
        }

        auto sequence = std::index_sequence_for<Args...>{};
        return handleImpl(sequence, args);
    }

    template<std::size_t... S>
    bool handleImpl(std::index_sequence<S...>, char const** args) {
        // both S and Args expanded
        return execute(Convert<Args>{}(args[S])...);
    }
};

int main() {
    Command<int, std::string, double> c;

    char const* args[] = {"1", "blah", "1.2"};

    c.handle(3, args);
}

Live Example