C++具有特定接口的类型进行模板专用化



假设我有这样的模板:

template<class T>
class A
{
...
};

我希望这个模板只有在替换代替T具有特定接口的类型时才能专门化。例如,此类型必须具有以下两种方法:

int send(const char* buffer, size_t size);
int receive(char* buffer, size_t size);

如何对模板进行此限制? 感谢您的帮助!

上级:

这个问题是关于SFINAE的?而不是关于内在或类设计。

非常简单的方法是在A中使用T::sendT::receive,任何未实现这些的类型都将导致编译时无法实例化模板。您只需要 SFINAE 来区分模板的专业化。

例如

template<class T>
class A
{
void useT(T & theT)
{
char buf[20]
theT.send("Some Thing", 11);
theT.recieve(buf, 20);
}
};

另一个答案显然更可取,但由于您明确要求SFINAE,因此您可以:

#include <iostream>
#include <utility>
// std::void_t in C++17
template < typename... >
using void_t = void;

// Check if there is a member function "send" with the signature
// int send(const char*, size_t)
template < typename T >
using send_call_t = decltype(std::declval<T>().send(std::declval<char const *>(), std::declval<size_t>()));
template < typename, typename = void_t<> >
struct is_send_callable : std::false_type {};
template < typename T >
struct is_send_callable< T, void_t< send_call_t<T> > > : std::is_same< send_call_t<T>, int > {};

// Check if there is a member function "receive" with the signature
// int receive(const char*, size_t)
template < typename T >
using recv_call_t = decltype(std::declval<T>().receive(std::declval<char *>(), std::declval<size_t>()));
template < typename, typename = void_t<> >
struct is_recv_callable : std::false_type {};
template < typename T >
struct is_recv_callable< T, void_t< recv_call_t<T> > > : std::is_same< recv_call_t<T>, int > {};

// Make a struct which implements both
struct sndrecv
{
int send(const char* buffer, size_t size)
{
std::cout << "Send: " << buffer << ' ' << size << 'n';
return 0;
}
int receive(char* buffer, size_t size)
{
std::cout << "Receive: " << buffer << ' ' << size << 'n';
return 0;
}
};

// Disable A if T does not have send and receive
template < typename T, typename >
class A;
template < typename T, typename = typename std::enable_if< is_send_callable<T>::value && is_recv_callable<T>::value >::type >
class A {};

int main() {
A<sndrecv> a;
//A<int> b; // BOOM!
}

检查类是否具有具有某些签名的方法是SFINAE原理的常见应用。例如,您可以在那里和那里检查。

最新更新