I need to make a wrapper class template that can possibly contain a reference member. I have both copy and move constructors defined, where references of the wrapped type are passed as arguments. This is all good if the type is not a reference. But if it is, both type& and type&& become lvalue references, and the two constructors conflict with each other.
I tried defining one set of constructors for the case where the type is not a reference and another for when it is, making use of the requires clause, as shown in the code below. But this doesn't compile if the type is a reference! GCC somehow treats the poisoned constructors as still valid.
Am I misunderstanding how requires works, or is this a bug? Here is the same example in the compiler explorer: https://godbolt.org/z/qjMxx3nGE
#include <type_traits>
template <typename T>
struct S {
using type = T;
type x;
S(const type& x) requires(!std::is_reference_v<type>)
: x(x) { }
S(type&& x) requires(!std::is_reference_v<type>)
: x(x) { }
S(type x) requires(std::is_reference_v<type>)
: x(x) { }
};
int main(int argc, char** argv) {
int i = 5;
S<int&> s(i);
return s.x;
}