将常量文字数组传递给函数而不将其声明为变量

时间:2017-06-27 00:55:06

标签: c++ arrays c++11 stdinitializerlist

我有一个表示值的类,可以假设单个数字的值,单个字符串,值数组或键值对的映射。

这是一个很好的定义:

class Foo {
public:
    typedef enum { STRING, NUMBER, ARRAY, MAP } data_type;
    struct str_less {
        bool operator()(const char *a, const char *b) const {
            return strcmp(a,b)<0;
        }
    };
    inline Foo(int n):type(NUMBER),number_value(n) { }
    inline Foo(double n):type(NUMBER),number_value(n) { }
    inline Foo(const char *s):type(STRING),string_value(s) { }
    inline Foo(const std::initializer_list<std::pair<const char *const,Foo>> &arg):type(MAP),map_value(arg) { }    
    template<size_t N> inline Foo(const Foo (&arg)[N]):type(ARRAY) { std::copy(&arg[0], &arg[N], std::back_inserter(arg)); }
    inline Foo(const std::vector<Foo> &arg):type(ARRAY),array_value(arg) { }
private:
  data_type type;
  double number_value = 0;
  const char *string_value = "";
  std::vector<Foo> array_value;
  std::map<const char *,Foo, str_less> map_value;
};

我只对从编译时给出的值实例化这个类感兴趣...出于我的目的,它永远不会在变量作为参数的运行时被调用。

由于Foo中的构造函数,在编译时指定的任何文字值都会自动转换为Foo,然后我可以以类似json的方式指定文字,例如:

Foo({
    {"number_key", 100},
    {"array_key", std::vector<Foo>
        {1, 3, 4,
            {
                {"inner_key", "value"},
                {"second_key", 500}}, "abc"}}});
但是,正如您所看到的那样,需要注意的是,我似乎需要对std :: vector进行显式强制转换才能支持数组类型。在C ++ 11中是否有任何方法可以将某种类型的文字数组传递给函数,以便我可以适当地调用template<size_t N> Foo::Foo(const Foo (&arg)[N])?我更喜欢这个,因为要求显式向量转换感觉很尴尬,并且绝对不是与其他构造函数自动转换其类型的同类。我想知道是否有其他方法可以利用智能自动类型转换以更统一和简洁的方式进行?

之前我见过这样的代码:

template<std::size_t N> void do_stuff(const char (&str)[N]) ...

可以使用字符串文字调用,因此从概念上讲,该机制似乎存在用于理解编译时文字数组,但有没有办法指定类型的常量数组其他而不是{{1 }}?

1 个答案:

答案 0 :(得分:1)

这样的事情应该有效:

template <typename... Args>
Foo(Args&&... args) :
  array_value{Foo(std::forward<Args>(args))...}
{}

Foo foo(4.2, "hello");

Proof of concept