Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use std::constructible_from

I am starting on C++ concepts and have trouble using them.

E.g. Here I want to make an optimistic create_unique function.

template<typename Arg, constructible_from<Arg> CreatedClass >       *1
unique_ptr<CreatedClass>
create_unique( Arg && arg ) {
    return make_unique<CreatedClass>( forward<Arg>( arg ) );
}
template<typename CreatedClass, typename Arg, 
         enable_if_t< !is_constructible<CreatedClass, Arg>::value, int > = 0>   *2
unique_ptr<CreatedClass>
create_unique( Arg && arg ) {
    throw runtime_error( "CreatedClass is not constructible from arg." );
}

int main() {
    auto x = create_unique2<string>("Hello"s);    *3
    // auto x = create_unique2<string>(42);
}

This does not compile because in *1 CreatedClass is placed after Arg. So in order for that to compile I have to explicitly specify both template arguments.

    auto x = create_unique2<string, string>("Hello"s);

If I write

template<constructible_from<string> CreatedClass, typename Arg >       *1
unique_ptr<CreatedClass>
create_unique( Arg && arg ) {
    return make_unique<CreatedClass>( forward<Arg>( arg ) );
}

then *3 compiles, but now CreatedClass is no longer dependent on Arg.

After this, how do I specify the negative case *2? It seems a bit un-clean to use the old-school enable_if.

like image 919
Generic Name Avatar asked Sep 19 '25 00:09

Generic Name


1 Answers

Just do:

template <typename CreatedClass, typename Arg>
    requires std::constructible_from<CreatedClass, Arg>
auto create_unique(Arg&&) -> std::unique_ptr<CreatedClass>

You don't have to use the terser constraint syntax - requires is always available.

The negative case would then be an overload with no constraint:

template <typename CreatedClass, typename Arg>
auto create_unique(Arg&&) -> std::unique_ptr<CreatedClass>

The more constrained case would be preferred. But this is highly questionable, why would you want to defer this error to runtime? Seems way better to diagnose at compile type by just not having a viable overload of create_unique...

like image 69
Barry Avatar answered Sep 21 '25 15:09

Barry