I would like to implement this function (or a similar one, see the requirements below) in 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
//(...)
);
}
};
As you see I would like to introduce a macro-based interface (it is necessary, it does a lot of other Qt related magic).
DEF_BINDING returns a constexpr object of an user-defined struct (BindingInfo
- it contains a few const char*
and size_t
members, it can be replaced with any struct or template that can contain the same).
I don't want to force the programmer to count the bindings manually because it would be inconvenient. The solution above is the closest I could figure out, but I would like to solve the followings in C 11:
- Needs to return an array of elements (array like, using
std::array
is not a must-have) - Must be compile time
- The items must be defined only once (do not want to enumerate the array elements twice)
- Must be header-only (static constexpr member defined in the cpp file cannot work, non-ODR regulated use can work)
- The array-size must be auto-deduced
The solution can use any kind of C 11 magic. I hope we can figure out something :)
UPDATE: In the original post I forgot to mention a really important fact: getRawBindings is inside a struct.
CodePudding user response:
How about using trailing return type?
#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)...);
}
};
Then you can call getRawBindings()
like this:
constexpr auto raw_bingdings = DataBinding::getRawBindings(
DEF_BINDING(int, stateProp, stateParam),
DEF_BINDING(float, areaProp, areaParam)
// ...
);
CodePudding user response:
Trailing return type should do the job:
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
//(...)
);
}
};
To avoid the repetition, MACRO might help:
#define RETURN(Expr) decltype(Expr) { return Expr; }
and then
struct DataBinding {
static constexpr auto getRawBindings()
-> RETURN(
asConstArray(
DEF_BINDING(int, stateProp, stateParam), //BindingInfo constexpr object
DEF_BINDING(float, areaProp, areaParam) //BindingInfo constexpr object
//(...)
)
)
};