1

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?

schorsch312
  • 5,553
  • 5
  • 28
  • 57
  • 1
    use constexpr if – mfnx Mar 18 '21 at 13:11
  • `static_assert` is checked at compile time, `if`-`else` is at runtime, so the `else` block still needs to compile, which is when the assertion fails. Perhaps `if constexpr` would work? – Biffen Mar 18 '21 at 13:11

2 Answers2

4

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

bartop
  • 9,971
  • 1
  • 23
  • 54
2

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;
}
apple apple
  • 10,292
  • 2
  • 16
  • 36