Search code examples
c++templatesstatic-assert

How to give nice static_assert message to users when the template return type prevents it from instantiation?


Let's assume that I want to write function that returns pointer the first element of nonempty container.

// REQUIRES: c not empty
template<typename C>
auto pointer_to_first(C& c) -> decltype( &(*c.begin()) ){
    return nullptr; // TODO: implement
}

If I try to use this with vector<bool>

vector<bool> vb{false, false, true};
pointer_to_first(vb);

Compiler gives error message confusing to beginners:

error: taking address of temporary [-fpermissive] auto pointer_to_first(C& c) -> decltype(&(*c.begin())){

It is confusing since beginners do not know about proxy that vector<bool> uses and vb is not a temporary.

So I wish to add static_asserts that the container can not be vector<bool>, also that container must have begin(), end()... I know how to do that but the problem is that since overload resolution fails users will only see the compiler error message.

Is there a way to get around this?


Solution

  • Until we have concept, you may add an extra layer to allow to have static_assert and avoid SFINAE:

    // Your SFINAE function:
    template<typename C>
    auto pointer_to_first_impl(C& c) ->   decltype(&(*c.begin())){
      return nullptr;// TODO: implement
    }
    
    template<typename C>
    decltype(auto) pointer_to_first(C& c)
    {
        // You need to implement the traits for the check
        static_assert(my_cond<C>::value, "type is incorrect");
        return pointer_to_first_impl(c);
    }