Home > database >  Constrainted auto std::convertible_to with initializer list
Constrainted auto std::convertible_to with initializer list

Time:11-01

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
  • Related