Why does the following define the !
and -
operators, but fail to define the ~
operator?
#include <type_traits>
#include <cstdint>
#include <typeinfo>
#include <cstdio>
template <typename T, T v>
struct integral_constant
: std::integral_constant<T, v>
{
};
#define DECL_UNARY_OP(op) \
template <typename T, T t> \
constexpr integral_constant<decltype(op t), (op t)> \
operator op(integral_constant<T, t>) \
{ return {}; } \
DECL_UNARY_OP(~);
DECL_UNARY_OP(-);
DECL_UNARY_OP(!);
int main() {
constexpr auto x = integral_constant<uint8_t, 1>{};
constexpr auto y = integral_constant<uint8_t, 10>{};
constexpr auto z = integral_constant<uint8_t, 100>{};
puts(typeid(-x).name()); // integral_constant<...>
puts(typeid(~y).name()); // int!
puts(typeid(!z).name()); // integral_constant<...>
}
Compiling this on GCC-4.8.2 gives the following on godbolt, where you can clearly see that the middle operation has decayed away from an integral_constant
type.
Why is this happening?