は考え私は、このようなテンプレートを持っています。たとえば、このタイプには次の2つの方法が必要です。С++テンプレートの特殊化は
int send(const char* buffer, size_t size);
int receive(char* buffer, size_t size);
テンプレートでこの制限を適用するにはどうすればよいですか。 助けてくれてありがとう!
UPD:
この質問はSFINAEについてですか?それ以来かクラスデザインではありません。
は考え私は、このようなテンプレートを持っています。たとえば、このタイプには次の2つの方法が必要です。С++テンプレートの特殊化は
int send(const char* buffer, size_t size);
int receive(char* buffer, size_t size);
テンプレートでこの制限を適用するにはどうすればよいですか。 助けてくれてありがとう!
UPD:
この質問はSFINAEについてですか?それ以来かクラスデザインではありません。
他の答えが明らかに好ましいが、あなたが明示的に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!
}
あなたの答えに感謝します!私はすぐにそれを試してみましょう! –
T::send
とT::receive
をA
に入れるのが最も簡単な方法ですが、これらを実装していないタイプであれば、コンパイル時にテンプレートをインスタンス化できません。テンプレートの特殊化を区別するために必要なのはSFINAEだけです。
template<class T>
class A
{
void useT(T & theT)
{
char buf[20]
theT.send("Some Thing", 11);
theT.recieve(buf, 20);
}
};
あなたの返信ありがとう!あなたはいくつかのコードや例を提供できますか? –
テンプレートを抽象基本クラス要件と混同しないでください。特定の関数セットが必要な場合は、そのインターフェイスをクラスとして定義し、単純な型指定された要件にします。 – tadman
[クラスに署名付きの関数があるかどうかを確認する](https://stackoverflow.com/questions/24975147/check-if-class-has-function-with-signature) –
@tadmanの複製が可能です。あなたが興味を持っているすべてのタイプに基本クラスを追加することができます。 – Caleth