Search code examples
c++visual-c++static-assert

Visual C: Custom Error Message in Template Class


The code below fails (as expected). What bothers me is the error message. It does not clearly say what the problem is. I would have expected something like “cannot convert from const char* to int”. Instead, it says "cannot convert from 'initializer list' to 'B<int>'", which becomes less clear when other, complex, types are involved.

How do I add a custom error message? The actual class is much more complicated.

#include <vector>

template< typename T >
class B
{
  std::vector<T> v;
public:
  B( std::initializer_list<T> il ) : v{ il } {}
};

int main()
{
  B<int> b{ "a","b","c" }; // fails with cannot convert from 'initializer list' to 'B<int>'
}

Solution

  • If you only want to have a std::initializer_list<T> constructor then one thing you can do is provide a variadic template constructor and then have a static_assert inside the constructor that gives the error message that you want. This works because if you provide anything other then an std::initializer_list<T> the constructor will be a better match and the assert will fire. That would look like

    #include <vector>
    
    template< typename T >
    class B
    {
        std::vector<T> v;
    public:
        B( std::initializer_list<T> il ) : v{ il } {}
        template <typename... Args>
        // the sizeof...(Args) < 0 is needed so the assert will only fire if the constructor is called
        B(Args...) { static_assert(sizeof...(Args) < 0, "This class can only be constructed from a std::initializer_list<T>"); }
    };
    
    int main()
    {
        //B<int> b1{ "a","b","c" }; // uncomment this line to get static_assert to fire
        B<int> b2{ 1,2,3 };
    }