std::is_same else static assert

1.2k Views Asked by At

I like to to specialize a function with respect to a template type. This works fine with std::is_same.

Now, I like the code to not compile, if a not specialized type is given.

template <typename T>
constexpr double get(const T& item) const {
    if (std::is_same<T, SOME_TYPE>::value)
        return item.get();
    if (std::is_same<T, SOME_OTHER_TYPE>::value)
        return -1.0;
    else {
        // Compile time error, if this branch is created.
        static_assert(false, "Getter not implemented for Type");
        return -1.0;
    }
}

This snippet does not compile, with the error message

error: static assertion failed with "Getter not implemented for Type"

although the function is only instantiated with SOME_TYPE or SOME_OTHER_TYPE.

How can I make sure at compile time, that no others types than SOME_TYPE or SOME_OTHER_TYPE are used?

2

There are 2 best solutions below

0
bartop On BEST ANSWER

Simplest way is doing something like this:

template <typename T>
constexpr double get(const T& item) const {
    static_assert(
        std::is_same<T, SOME_TYPE>::value || std::is_same<T, SOME_OTHER_TYPE>::value,
        "Getter not implemented for Type");
    if constexpr (std::is_same<T, SOME_TYPE>::value) {
        return item.get();
    } else if constexpr (std::is_same<T, SOME_OTHER_TYPE>::value) {
        return -1.0;
    }
}

Note that your compiler needs to support C++17 so you can replace if with if constexpr.

EDIT: The constexpr if is needed here to avoid compilation error if SOME_OTHER_TYPE does not have get() member method. Therefore I have changed the code

0
apple apple On

If the presented code is what you want (i.e. each block are independent with each other), simply use overload functions.

constexpr double get(const SOME_TYPE& item){
   return item.get();
}
constexpr double get(const SOME_OTHER_TYPE&){
    return -1;
}