我想知道如何在不使用虚函数的情况下在C++中声明接口。经过一番互联网搜索我放在一起此解决方案:没有虚函数的C++接口
#include <type_traits>
using namespace std;
// Definition of a type trait to check if a class defines a member function "bool foo(bool)"
template<typename T, typename = void>
struct has_foo : false_type { };
template<typename T>
struct has_foo<T, typename enable_if<is_same<bool, decltype(std::declval<T>().foo(bool()))>::value, void>::type> : true_type { };
// Definition of a type trait to check if a class defines a member function "void bar()"
template<typename T, typename = void>
struct has_bar : false_type { };
template<typename T>
struct has_bar<T, typename enable_if<is_same<void, decltype(std::declval<T>().bar())>::value, void>::type> : true_type { };
// Class defining the interface
template <typename T>
class Interface{
public:
Interface(){
static_assert(has_foo<T>::value == true, "member function foo not implemented");
static_assert(has_bar<T>::value == true, "member function bar not implemented");
}
};
// Interface implementation
class Implementation:Interface<Implementation>{
public:
// If the following member functions are not declared a compilation error is returned by the compiler
bool foo(bool in){return !in;}
void bar(){}
};
int main(){}
我打算在一个项目中,我将只使用静态多态性使用这种设计策略。 我将在该项目中使用的C++标准是C++ 11。
您认为这种方法的优缺点是什么?
对我提出的代码有什么改进?
编辑1: 我刚刚意识到,从接口继承是不需要的。此代码还可以用于:
class Implementation{
Interface<Implementation> unused;
public:
bool foo(bool in){return !in;}
void bar(){}
};
编辑2-3: 的static_assert溶液(带或不带CRTP)和标准CRTP之间的一个主要区别是,CRTP不保证派生类实现所有接口成员。例如,下面的代码编译正确:
#include <type_traits>
using namespace std;
template< typename T>
class Interface{
public:
bool foo(bool in){
return static_cast<T*>(this)->foo(in);
}
void bar(){
static_cast<T*>(this)->bar();
}
};
class Implementation: public Interface<Implementation>{
public:
// bool foo(bool in){return !in;}
// void bar(){}
};
int main(){}
关于丢失成员函数的错误将仅当将所需要的功能FOO或酒吧编译器被返回。
我看到它的方式,static_assert解决方案比CRTP更像是一个接口声明。
你看着[CRTP(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)? – Amadeus
@Amadeus是的,很久以前,但不幸的是我忘记了它... – carlo
'class Implementation:Interface'。这是CRTP,没有别的。 CRTP是这个,没有别的。 'static_assert'是可选的,它们只提供更好的错误信息。 –