我正在尝试创建类
ServerLogic
,其中构造函数根据模板参数获取不同的参数并以不同的方式处理它(在这种情况下它将它们传递给endpoint
构造函数)
// Shortened version of code
using namespace boost::asio;
template <typename Protocol>
class ServerLogic
{
static_assert(
std::is_same_v<Protocol, local::stream_protocol> ||
std::is_same_v<Protocol, ip::tcp>
); // Allow using only either `local::stream_protocol` or
// `local::tcp` as Protocol
Protocol::endpoint *ep;
public:
ServerLogic(std::string sock_path)
requires std::is_same<Protocol, local::stream_protocol>::value
: ep(new Protocol::endpoint(sock_path))
{} // If Protocol is `local::stream_protocol` then create ep of
// `local::stream_protocol` due to it's constructor
ServerLogic(const ip::address &addr, unsigned short port)
requires std::is_same<Protocol, ip::tcp>::value
: ep(new Protocol::endpoint(addr, port))
{} // If Protocol is `ip::tcp` then create ep of `ip::tcp` protocol
// due to it's constructor, different from `local::stream_protocol`
// endpoint constructor
但是编译器给出了错误:
[build] /home/shkiperdesna/cppbot/src/ServerLogic.hpp: In instantiation of ‘ServerLogic<Protocol>::ServerLogic(const boost::asio::ip::address&, short unsigned int) requires is_same_v<Protocol, boost::asio::ip::tcp> [with Protocol = boost::asio::local::stream_protocol]’:
[build] /home/shkiperdesna/cppbot/src/ServerLogic.cpp:95:16: required from here
[build] /home/shkiperdesna/cppbot/src/ServerLogic.hpp:49:14: error: no matching function for call to ‘boost::asio::local::basic_endpoint<boost::asio::local::stream_protocol>::basic_endpoint(const boost::asio::ip::address&, short unsigned int&)’
...
我知道,尽管使用了
requires
关键字,编译器仍尝试使用两种协议来编译两个构造函数。如何解决这个问题并为不同的模板参数拆分构造函数?
另请参阅:如何禁用某些模板类型的类成员函数
您的问题是您的要求不依赖于成员函数的任何模板参数,而是依赖于整个类。因此,即使
new Protocol::endpoint(addr, port)
不满足,也会检查 requires std::is_same<Protocol, ip::tcp>::value
。
你必须将构造函数设为模板:
template <typename Protocol>
class ServerLogic
{
static_assert(
std::is_same_v<Protocol, local::stream_protocol> ||
std::is_same_v<Protocol, ip::tcp>
); // Allow using only either `local::stream_protocol` or
// `local::tcp` as Protocol
Protocol::endpoint *ep;
public:
template<typename U = Protocol>
ServerLogic(std::string sock_path)
requires std::is_same<U, local::stream_protocol>::value
: ep(new U::endpoint(sock_path))
{} // If Protocol is `local::stream_protocol` then create ep of
// `local::stream_protocol` due to it's constructor
template<typename U = Protocol>
ServerLogic(const ip::address &addr, unsigned short port)
requires std::is_same<U, ip::tcp>::value
: ep(new U::endpoint(addr, port))
{} // If Protocol is `ip::tcp` then create ep of `ip::tcp` protocol
// due to it's constructor, different from `local::stream_protocol`
// endpoint constructor