/* -*- C++ -*- * Serene Programming Language * * Copyright (c) 2019-2022 Sameer Rahmani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "serene/traits.h" #include "./test_helpers.cpp.inc" #include namespace serene { template class Printable : public TraitBase { public: Printable(){}; Printable(const Printable &) = delete; std::string Print() { return this->Object().Print(); } }; template class Analyzable : public TraitBase { public: Analyzable(){}; Analyzable(const Analyzable &) = delete; std::string Analyze() { 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; public: A(std::string a) : x(a){}; std::string Print() const { return "A: print"; } std::string Analyze() const { return "A: " + x; } }; template class B : public std::conditional, WithTrait, Printable, Analyzable>, WithTrait>::type { std::string y; public: B(std::string a) : y(a){}; std::string Print() const { return "B: print"; } std::string Analyze() const { return "B: " + y; } }; class C : public B { std::string z; std::string w; public: C(std::string a, std::string b, std::string c) : B(a), z(b), w(c){}; std::string Print() const { return z; } std::string Analyze() const { return w; } }; class D : public WithTrait { public: std::string Print() const { return "D: print"; } 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