I am a bit of a noob to C++20, and I only recently have been able to use C++11/14 so I am trying to update my knowledge and I'm having a bit of trouble trying to use concept requirements. My goal is to ensure that a class of type SocketAddress only takes a type of IpV4Address or IpV6Address in its constructor, while using a template constructor so that I don't have to have 6 different constructor definitions for passing by value, ref, or r-value.
I am able to compile the class of SocketAddress when it is defined as:
template <typename T>
concept IpAddress = std::is_base_of<IpV4Address, T>::value || std::is_base_of<IpV6Address, T>::value;
class SocketAddress
{
public:
SocketAddress() = delete;
template <typename T> requires IpAddress<T>
SocketAddress(T&& ip_address, const uint16_t port) noexcept;
};
template <typename T> requires IpAddress<T>
SocketAddress::SocketAddress(T&& ip_address, const uint16_t port) noexcept :
m_ip_address(std::forward<T>(ip_address))
{
}
However, when I actually attempt to construct a SocketAddress in my tests I get the compiler error:
error C2661: 'CrossPlatformSockets::SocketAddress::SocketAddress': no overloaded function takes 2 arguments
Where my test code is:
SocketAddress socket_address(IpV4Address("127.0.0.1"), 8000);
I'm not really sure what I am missing here such that the compiler is unable to detect the constructor I have defined that takes two inputs. If anyone can help me learn how to use these concepts or point out what is wrong I would greatly appreciate it! I know I could not use concepts, and use some form of static assert/ugly SNFINAE-type solution, however I want to learn the new stuff!
This is dumb but a clean and rebuild literally fixed my problem.
Additionally given @PatrickRoberts suggestion, my concept is now defined as:
template <typename T>
concept IpAddress = std::is_base_of<IpV4Address, std::remove_cvref_t<T>>::value ||
std::is_base_of<IpV6Address, std::remove_cvref_t<T>>::value;