diff --git a/include/serene/traits.h b/include/serene/traits.h index 4f1582e..a0a61d3 100644 --- a/include/serene/traits.h +++ b/include/serene/traits.h @@ -109,26 +109,6 @@ protected: }; }; -template -class Printable : public TraitBase { -public: - Printable(){}; - Printable(const Printable &) = delete; - std::string Print() const { return this->Object().Print(); } -}; -template -class Analyzable : public TraitBase { -public: - Analyzable(){}; - Analyzable(const Analyzable &) = delete; - std::string Analyze() const { return this->Object().Analyze(); } -}; - -template std::string Print(Printable &t) { return t.Print(); } - -template std::string Analyze(Analyzable &t) { - return t.Analyze(); -}; }; // namespace serene #endif diff --git a/src/tests/traits_tests.cpp.inc b/src/tests/traits_tests.cpp.inc index d3b1df8..c92edb5 100644 --- a/src/tests/traits_tests.cpp.inc +++ b/src/tests/traits_tests.cpp.inc @@ -28,6 +28,28 @@ namespace serene { +template +class Printable : public TraitBase { +public: + Printable(){}; + Printable(const Printable &) = delete; + std::string Print() const { return this->Object().Print(); } +}; + +template +class Analyzable : public TraitBase { +public: + Analyzable(){}; + Analyzable(const Analyzable &) = delete; + std::string Analyze() const { return this->Object().Analyze(); } +}; + +template std::string Print(Printable &t) { return t.Print(); } + +template std::string Analyze(Analyzable &t) { + return t.Analyze(); +}; + class A : public WithTrait { std::string x; @@ -40,7 +62,9 @@ public: }; template -class B : public std::conditional, WithTrait, Printable, Analyzable>, WithTrait>::type { +class B : public std::conditional, + WithTrait, Printable, Analyzable>, + WithTrait>::type { std::string y; @@ -63,7 +87,6 @@ public: std::string Analyze() const { return w; } }; - class D : public WithTrait { public: std::string Print() const { return "D: print"; } @@ -71,26 +94,37 @@ public: std::string Analyze() const { return "D: analyze with no trait"; } }; +template +class MetaTrait : public WithTrait {}; +class E : public MetaTrait { +public: + std::string Print() const { return "E: print"; }; + + std::string Analyze() const { return "E: in E"; }; +}; TEST_CASE("Trait functionality tests", "[Traits]") { auto a = A("in A"); auto b = B("in B"); auto c = C("gray", "white", "black"); auto d = D(); + auto e = E(); + CHECK(Print(a) == "A: print"); CHECK(Print(b) == "B: print"); CHECK(Print(c) == "white"); CHECK(Print(d) == "D: print"); + CHECK(Print(e) == "E: print"); CHECK(Analyze(a) == "A: in A"); CHECK(Analyze(b) == "B: in B"); CHECK(Analyze(c) == "black"); + CHECK(Analyze(e) == "E: in E"); // Even though D has a Analyze method, It's not Analyzable to the // Analyze function signature won't match CHECK(d.Analyze() == "D: analyze with no trait"); - }; } // namespace serene