fork(2) download
  1. #include <type_traits>
  2. #include <memory>
  3. #include <iostream>
  4.  
  5. template<class T>
  6. class ObjectMustBeCreatedType : public std::false_type {
  7. // needed for proper static_assert<T> below
  8. };
  9.  
  10. // default function that has to be specialized, otherwise compiler error
  11. template<class T>
  12. std::shared_ptr<T> CreateObject(const std::string &path) {
  13. static_assert(ObjectMustBeCreatedType<T>::value,
  14. "please specialize this for your class");
  15. }
  16.  
  17. // SFINAE to detect static T::Create function
  18. template <
  19. typename T,
  20. typename = typename std::enable_if<
  21. std::is_same<
  22. std::shared_ptr<T>,
  23. decltype(T::Create(std::string{}))
  24. >::value
  25. >::type
  26. >
  27. std::shared_ptr<T> CreateObject(const std::string &s) {
  28. return T::Create(s); // if T::Create is found, call it
  29. }
  30.  
  31. // for this class the SFINAE version should be triggered
  32. // and CreateObject<AutomaticClass> should be instantiated automatically
  33. struct AutomaticClass {
  34. static std::shared_ptr<AutomaticClass> Create(const std::string &s) {
  35. std::cout << "AutomaticClass::Create" << std::endl;
  36. return std::make_shared<AutomaticClass>();
  37. }
  38. };
  39.  
  40. // for this class CreateObject is manually specialized below
  41. struct ManualClass {
  42. ManualClass(const std::string &s) {
  43. std::cout << "ManualClass constructor: " << s << std::endl;
  44. }
  45. };
  46.  
  47. // manual CreateObject<ManualClass> specialization
  48. template<>
  49. std::shared_ptr<ManualClass> CreateObject(const std::string &s) {
  50. std::cout << "CreateObject<ManualClass>" << std::endl;
  51. return std::make_shared<ManualClass>(s);
  52. }
  53.  
  54. int main() {
  55. // this works
  56. CreateObject<ManualClass>("ManualClass test");
  57.  
  58. // produces compile errors
  59. CreateObject<AutomaticClass>("AutomaticClass test");
  60.  
  61. return 0;
  62. }
  63.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In function ‘int main()’:
prog.cpp:59:59: error: call of overloaded ‘CreateObject(const char [20])’ is ambiguous
         CreateObject<AutomaticClass>("AutomaticClass test");
                                                           ^
prog.cpp:12:24: note: candidate: std::shared_ptr<_Tp1> CreateObject(const string&) [with T = AutomaticClass; std::__cxx11::string = std::__cxx11::basic_string<char>]
     std::shared_ptr<T> CreateObject(const std::string &path) {
                        ^~~~~~~~~~~~
prog.cpp:27:24: note: candidate: std::shared_ptr<_Tp1> CreateObject(const string&) [with T = AutomaticClass; <template-parameter-1-2> = void; std::__cxx11::string = std::__cxx11::basic_string<char>]
     std::shared_ptr<T> CreateObject(const std::string &s) {
                        ^~~~~~~~~~~~
stdout
Standard output is empty