Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;具有特定接口的类型的模板专门化_C++_Templates_Template Specialization - Fatal编程技术网

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!
}