Skip to content

Instantly share code, notes, and snippets.

@Riyaaaaa
Last active June 21, 2017 08:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Riyaaaaa/197de64db6c7bba488a7 to your computer and use it in GitHub Desktop.
Save Riyaaaaa/197de64db6c7bba488a7 to your computer and use it in GitHub Desktop.
【C++】CRTPによる静的インターフェースクラスはライブラリ実装において不適切+解決法 ref: http://qiita.com/Riyaaaa_a/items/a9af401520f238f45b80
template<class T>
class Base;
class Derived : Base<Derived>;
template<class T>
class Interface{
public:
void function(){ static_cast<T&>(this)->function(); }
};
class Derived1 : Interface<Derived1>{
public:
void function(){ std::cout << "Derived1" << std::endl; }
};
class Derived2 : Interface<Derived2>{
public:
};
main.cpp:8:9: error: static_assert failed "add is not defined"
static_assert(std::is_same<decltype(std::declval<T>().add(std::declval<int>(),std::declval<int>())),int>::value,"ad...
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:12:7: note: in instantiation of member function 'Interface<Derived1>::Interface' requested here
class Derived1 : public Interface<Derived1>{
class Derived1 : Interface<Derived1>{
public:
int _a;
Derived1(){ std::cin >> _a; }
int add(int a, int b){ return a + b; }
};
int main(){
002A12A0 push ebp
002A12A1 mov ebp,esp
002A12A3 sub esp,8
002A12A6 mov eax,dword ptr ds:[002A4000h]
002A12AB xor eax,ebp
002A12AD mov dword ptr [ebp-4],eax
Derived1 a;
002A12B0 mov ecx,dword ptr ds:[2A3030h]
002A12B6 lea eax,[a]
002A12B9 push eax
002A12BA call dword ptr ds:[2A3038h]
a.add(1, 1);
return 0;
}
template <class T> inline void ignore_unused_variable_warning(T const&) {}
template <class T>
void functionRequires()
{
void (T::*fptr)() = &T::function;
ignore_unused_variable_warning(fptr);
}
template<class T>
class Interface{
void constraint() {
T t;
t.function();
}
typedef void (Interface<T>::* type)();
template <type _Tp1>
struct Check { };
typedef Check<& Interface<T>::constraint> _Check;
};
#define CLASS_REQUIRE(TT, NS, Concept) \
typedef void (NS::Concept <TT>::* func##TT##Concept)(); \
template <func##TT##Concept _Tp1> \
struct Concept_checking_##TT##Concept { }; \
typedef Concept_checking_##TT##Concept< \
& NS::Concept<TT>::constraint> \
Concept_checking_typedef_##TT##Concept
// デフォルトコンストラクタの定義を要求する制約
template<class TT>
struct DefaultConstructible {
void constraint() {
TT a;
ignore_unused_variable_warning(a);
}
};
template<class T>
class Interface {
CLASS_REQUIRE(T, , DefaultConstructible);
};
class myclass : Interface <myclass> {};
class Interface{
public:
virtual void function()=0;
virtual ~Interface()=default;
};
class Derived1 : Interface{
public:
void function(){ std::cout << "Derived1" << std::endl; }
};
class Derived2 : Interface{
public:
};
int main(){
Derived1 a;
Derived2 b;
a.function();
b.function();
return 0;
}
main.cpp:35:15: error: variable type 'Derived22' is an abstract class
Derived22 b;
^
main.cpp:20:17: note: unimplemented pure virtual method 'function' in 'Derived22'
virtual void function()=0;
main.cpp:6:21: error: non-const lvalue reference to type 'Derived2' cannot bind to a temporary of type 'Interface<Derived2> *'
void function(){ static_cast<T&>(this)->function(); }
^ ~~~~
main.cpp:23:7: note: in instantiation of member function 'Interface<Derived2>::function' requested here
b.function();
^
main.cpp:6:42: error: member reference type 'Derived2' is not a pointer; maybe you meant to use '.'?
void function(){ static_cast<T&>(this)->function(); }
int main(){
Derived1 a;
Derived2 b;
a.function();
//b.function();
return 0;
}
template<class T>
class Interface{
public:
Interface(){
static_assert(std::is_same<decltype(std::declval<T>().function()),void>::value,"function is not defined");
}
};
static_assert(std::is_same<decltype(std::is_same<std::declval<T>().関数名(std::declval<引数1>(),
...,
std::declval<引数n>()),
返り値の型>::value,
"迫真怒りのメッセージ");
#include<iostream>
#include<utility>
template<class T>
class Interface{
public:
Interface(){
static_assert(std::is_same<decltype(std::declval<T>().add(std::declval<int>(),std::declval<int>())),int>::value,"add is not defined");
}
};
class Derived1 : Interface<Derived1>{
public:
double add(int a,int b){return a+b;}
};
int main(){
Derived1 a;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment