2017-07-14 48 views
2

假设我有这样的模板:С++与具有一定的接口类型模板特

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

我想这个模板可以专门只有将代替T替代型有一定的接口。例如,此类型必须具有以下两种方法:

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

如何在模板上设置此限制? 感谢您的帮助!

UPD:

这个问题是关于SFINAE?不是关于内部设计或课堂设计。

+2

不要将模板与抽象基类要求混淆。如果您需要一组特定的功能,请将该接口定义为一个类,并将其作为一个简单的类型化需求。 – tadman

+2

可能重复[检查类是否具有签名功能](https://stackoverflow.com/questions/24975147/check-if-class-has-function-with-signature) –

+0

@tadman,假设您可以添加基类到您感兴趣的所有类型。 – Caleth

回答

1

其他答案显然是首选的,但因为你明确地要求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! 
} 
+0

感谢您的回答!我会尽快尝试! –

5

非常简单的方法是在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); 
    } 
}; 
+0

感谢您的回复!你能提供一些代码或例子吗? –

0

检查类有方法,有一定的签名是SFINAE原则常见的应用。例如,您可以检查therethere

相关问题