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 中解决以下问题:
- 需要return一个元素数组(类似数组,使用
std::array
是
不是 must-have)
- 必须是编译时
- 项目必须只定义一次(不想枚举数组元素两次)
- 必须是 header-only(静态 constexpr 成员定义在
cpp 文件无法工作,non-ODR 规范使用可以工作)
- 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
//(...)
)
)
};
我想在 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 中解决以下问题:
- 需要return一个元素数组(类似数组,使用
std::array
是 不是 must-have) - 必须是编译时
- 项目必须只定义一次(不想枚举数组元素两次)
- 必须是 header-only(静态 constexpr 成员定义在 cpp 文件无法工作,non-ODR 规范使用可以工作)
- 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
//(...)
)
)
};