1

Consider the following code (should be able to copy-paste directly into godbolt):

#include <type_traits>

template<typename T>
constexpr bool isInt() {
    return std::is_base_of<int, std::remove_reference_t<T>>::value;
}

template<typename T>
constexpr bool isInt(const T& t) {
    return isInt<T>();
}

class myClass {
    public:
        template<typename T1>
        bool doThing(const T1& t1) {
            constexpr bool x1 = isInt(t1); // compile error
            constexpr bool x2 = isInt<decltype(t1)>();
            constexpr bool x3 = isInt(1);
            constexpr bool x4 = isInt<int>();

            return false;
        }
};

int main() {
    myClass x;
    x.doThing(1);

    return 0;
}

In this scenario everything compiles fine except for the "x1" assignment. The error I get is "'t1' is not a constant expression".

In this case, the only reason I'm passing in "t1" is for the convenience of having the function deduce the type for me. But apparently that's not possible? I don't have a great understanding of how constexpr works, so I'm hoping to understand why this is problem.

Thanks!

EDIT:

Forgot to add this, but if the method is not templated, then it will compile. AKA:

bool doThing2(const int i) {
    constexpr bool y1 = isInt(i);
    return y1;
}

Compiles fine.

rmsantos
  • 105
  • 6
  • 2
    A function parameter is never a constant expression. – NathanOliver Oct 27 '22 at 20:25
  • Then why does this compile: bool doThing2(const int i) { constexpr bool y1 = isInt(i); return y1; } – rmsantos Oct 27 '22 at 20:27
  • 2
    The problem here is specifically that `t1` is a reference. Make `doThing` take the argument by-value and it will work. This is an unfortunate special requirement imposed on references used inside constant expressions that will be relaxed with C++23, so that your code will work fine then. – user17732522 Oct 27 '22 at 20:28
  • W.E.Brown [about templated functions](https://youtu.be/NIDEjY5ywqU?t=203). – Evg Oct 27 '22 at 20:45
  • note: your `isInt` is just `false`, you should use `std::is_same`, not `is_base_of` for `int` – apple apple Oct 27 '22 at 21:30

0 Answers0