C++ C++;具有特定接口的类型的模板专门化
假设我有这样的模板:C++ C++;具有特定接口的类型的模板专门化,c++,templates,template-specialization,C++,Templates,Template Specialization,假设我有这样的模板: template<class T> class A { ... }; 如何对模板进行此限制? 谢谢你的帮助 UPD: 这个问题是关于SFINAE的?与内部或类设计无关。非常简单的方法是在A中使用T::send和T::receive,任何未实现这些的类型都将导致编译时无法实例化模板。您只需要SFINAE来区分模板的专业化 e、 g 模板 甲级 { 无效使用(T&T) { char buf[20] 发送(“某物”,11); t.接收(buf,20); } }
template<class T>
class A
{
...
};
如何对模板进行此限制?
谢谢你的帮助
UPD:
这个问题是关于SFINAE的?与内部或类设计无关。非常简单的方法是在
A
中使用T::send
和T::receive
,任何未实现这些的类型都将导致编译时无法实例化模板。您只需要SFINAE来区分模板的专业化
e、 g
模板
甲级
{
无效使用(T&T)
{
char buf[20]
发送(“某物”,11);
t.接收(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!
}
#包括
#包括
//C++17中的std::void\u t
模板
使用void\u t=void;
//检查是否有带有签名的成员函数“send”
//int发送(常量字符*,大小\u t)
模板
使用send_call_t=decltype(std::declval().send(std::declval(),std::declval());
模板
结构是可调用的:std::false\u类型{};
模板
结构是可调用的>:std::是相同的{};
//检查是否有带有签名的成员函数“receive”
//int接收(常量字符*,大小\u t)
模板
使用recv_call_t=decltype(std::declval().receive(std::declval(),std::declval());
模板
结构是可调用的:std::false\u类型{};
模板
结构是可调用的>:std::is\u same{};
//创建一个同时实现这两者的结构
结构sndrecv
{
int发送(常量字符*缓冲区,大小)
{
std::cout检查类是否具有具有特定签名的方法是SFINAE原则的常见应用。例如,您可以检查和。不要将模板与抽象基类需求混淆。如果您需要一组特定的函数,请将该接口定义为类,并使其成为简单的类型化需求。@tadman的可能重复假设你可以把基类添加到你感兴趣的所有类型。@ Calthe就是多重继承的全部。直到C++有了协议支持,事情就是这样。@我的意思是,你可能从第三方接收对象,在那里你不控制实例化,所以你不能。更改类别谢谢你的回复!你能提供一些代码或示例吗?
template<class T>
class A
{
void useT(T & theT)
{
char buf[20]
theT.send("Some Thing", 11);
theT.recieve(buf, 20);
}
};
#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!
}