c ++ 11返回未知数量元素数组的方法

c++11 way of returning an array of unknown number of elements

我想在 C++11 中实现此功能(或类似功能,请参阅以下要求):

template<typename... ARGS>
constexpr std::array<const typename std::common_type<ARGS...>::type, sizeof...(ARGS)> asConstArray(ARGS&&... args)
{
    return {std::forward<ARGS>(args)...};
}

struct DataBinding {
    static constexpr auto getRawBindings()
    // HERE          ^- C++14, deduced to std::array<const BindingInfo, 2> in this case
    {
        return asConstArray(
            DEF_BINDING(int, stateProp, stateParam), //BindingInfo constexpr object
            DEF_BINDING(float, areaProp, areaParam)  //BindingInfo constexpr object
            //(...)
        );
    }
};

如你所见,我想介绍一个 macro-based 接口(这是必要的,它做了很多其他 Qt 相关的魔术)。

DEF_BINDING returns 一个 user-defined 结构的 constexpr object (BindingInfo - 它包含一些 const char*size_t 成员,它可以替换为任何可以包含相同的结构或模板)。

我不想强迫程序员手动计算绑定,因为这会很不方便。上面的解决方案是我能想到的最接近的解决方案,但我想在 C++11 中解决以下问题:

  1. 需要return一个元素数组(类似数组,使用std::array是 不是 must-have)
  2. 必须是编译时
  3. 项目必须只定义一次(不想枚举数组元素两次)
  4. 必须是 header-only(静态 constexpr 成员定义在 cpp 文件无法工作,non-ODR 规范使用可以工作)
  5. array-size必须是auto-deduced

解决方案可以使用任何一种 C++11 魔法。我希望我们能想出办法:)

更新:在原文中post我忘了提到一个非常重要的事实:getRawBindings 在一个结构中。

如何使用 尾随 return 类型

#include <array>

template<typename... ARGS>
constexpr std::array<const typename std::common_type<ARGS...>::type, sizeof...(ARGS)> 
asConstArray(ARGS&&... args)
{
    return {std::forward<ARGS>(args)...};
}

struct DataBinding {
    template<typename... BINDINGS>
    static constexpr auto getRawBindings(BINDINGS&&... bindings)
    -> decltype(asConstArray(std::declval<BINDINGS>()...))
    // ^^^ trailing return type
    {
        return asConstArray(std::forward<BINDINGS>(bindings)...);
    }
};

然后你可以这样调用getRawBindings():

constexpr auto raw_bingdings = DataBinding::getRawBindings(
                                 DEF_BINDING(int, stateProp, stateParam),
                                 DEF_BINDING(float, areaProp, areaParam)
                                 // ...
                               );

尾随 return 类型应该可以完成工作:

struct DataBinding {
    static constexpr auto getRawBindings()
    -> decltype(
        asConstArray(
            DEF_BINDING(int, stateProp, stateParam), //BindingInfo constexpr object
            DEF_BINDING(float, areaProp, areaParam)  //BindingInfo constexpr object
            //(...)
        )
    )
    {
        return asConstArray(
            DEF_BINDING(int, stateProp, stateParam), //BindingInfo constexpr object
            DEF_BINDING(float, areaProp, areaParam)  //BindingInfo constexpr object
            //(...)
        );
    }
};

为了避免重复,MACRO 可能会有所帮助:

#define RETURN(Expr) decltype(Expr) { return Expr; }

然后

struct DataBinding {
    static constexpr auto getRawBindings()
    -> RETURN(
        asConstArray(
            DEF_BINDING(int, stateProp, stateParam), //BindingInfo constexpr object
            DEF_BINDING(float, areaProp, areaParam)  //BindingInfo constexpr object
            //(...)
        )
    )
};