I'm trying to detect if an argument is a reference member, at compile time. It does not catch it and I can't figure it why.
#include <type_traits>
struct a {
a(): i1(42), i2(i1){}
int i1;
int& i2;
};
template <typename T>
void Field(T &field) {
if constexpr (std::is_pointer_v<T>) {
//handle pointer
} else if constexpr (std::is_reference_v<T>) {
static_assert(!std::is_reference_v<T>, "Reference not supported");
} else {
//handle value
}
}
int main()
{
a a_;
Field(a_.i2); // I want this to fail at compile time, but it's not
}
What am I doing wrong?
std::is_reference_v
works in principle, but not the way you're using it. You have a function template Field(T &field)
, where the template type parameter T
is not going to be deduced to a reference.
a a_;
Field(a_.i2); // calls Field<T>(T&) with [T = int]
// std::is_reference_v<int> is false
Whatever, you're trying to do here, you could:
std::reference_wrapper
and always accept a value parameter T field
std::type_identity_t<T> field
parameter, which forces the user to call Field<int&>(a_.i2)
manually
Field<decltype(a_.i2)>(a_.i2)