Hello stackoverflow people, I'm recently trying to learn c 20 constrainted auto as function parameters to reduce the boiler plate code.
I have a class template that is a wrapper for some data types, like std::int64_t, bool, double, std::string
, will probably add more in the future, and it has a function that takes the data type and an overloaded function that takes a std::initializer_list<data_t>
for array-ish manipulation.
template<typename data_t>
void set_data(data_t a_data)
template<typename data_t>
void set_data(std::initializer_list<data_t> a_dataList)
And these works fine if I call these setter functions directly.
In an api class that manages all these data, I have an exposed api that does basically same thing, I have this:
template<typename data_t>
void bind(Wrapper<data_t>& a_data, const std::convertible_to<data_t> auto a_value)
{
a_data.set_data(a_value);
}
template<typename data_t>
void bind(Wrapper<data_t>& a_data, const std::initializer_list<data_t> a_valueList)
{
a_data.set_data(a_value);
}
The first function works as intended, e.g I can pass any convertible data type to an wrapper of std::int64_t
, but the latter one if I want to pass an initializer_list to it I have to explicitly convert the type to data_t
like this
Wrapper<std::int64_t> iA;
bind(iA, 100); // works
iA.set_data(100) // works
bind(iA, {1,2,3,4,5}); // no
iA.set_data({1,2,3,4,5}); // works
bind(iA, {(std::int64_t)1, (std::int64_t)2, (std::int64_t)3, (std::int64_t)4});
// works
So my question finally came out: How do I implement something like std::convertible_to
with std::initializer_list
so I don't have to to type cast like above? Or is this doable at all?
CodePudding user response:
Your problem is C is deducing data_t
using both 1st and 2nd arguments. If they disagree, no cookie.
template<typename data_t>
void bind(Wrapper<data_t>& a_data, std::type_identity_t<std::initializer_list<data_t>> a_valueList)
this blocks deduction in 2nd argument.
CodePudding user response:
Okay after some digging which I should've done before posting the question, I found this solution: https://stackoverflow.com/a/34006263/17295222
template <typename data_t>
void Bind(Wrapper<data_t>& a_data, const std::convertible_to<data_t> auto... a_valueList) noexcept
{
a_data.set_data({static_cast<data_t>(a_valueList)...});
}
All I gotta do is to construct a std::initializer_list
of the required data_t type in place and skip the list construction when calling the function
bind(iA,1,2,3,4,5); // works, no need for brackets