2017-07-14 42 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

相關問題