/*! * \file TmetaDetection.cpp * * Copyright (C) 2018 Christos Choutouridis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * */ #include #include #include namespace TmetaDetection { using namespace utl; using namespace meta; /* * Types to behave like Fixtures */ struct Foo {}; struct Bar {}; template struct A { using type = T; // nested type A(int i, double d) : i_(i), d_(d) {} // declare a non-trivial constructor A& operator++() { ++i_; return *this; } // declare an operator // A sfinae function template ::type::value>> TT sfun () { return TT{}; } private: int i_; double d_; }; // A binary metafunction template struct mFun { using type = std::is_same ; }; // detectors template using try_type = typename T::type; template using try_none = typename T::none; template using try_ctor1= decltype (T(std::declval(), std::declval())); template using try_ctor2= decltype (T(std::declval())); template using try_ppT = decltype (++(std::declval())); template using try_Tpp = decltype (std::declval()++); template using try_sfun = decltype (std::declval().sfun()); /* * void_t */ TEST(TmetaDetection, VoidType) { EXPECT_EQ(true, (std::is_same>())); EXPECT_EQ(true, (std::is_same>())); } /* * not a type */ TEST(TmetaDetection, NotAType) { EXPECT_EQ(false, (std::is_default_constructible())); EXPECT_EQ(false, (std::is_destructible())); EXPECT_EQ(false, (std::is_copy_constructible())); EXPECT_EQ(false, (std::is_copy_assignable())); } /* * Idiom */ TEST(TmetaDetection, IsDetected) { EXPECT_EQ (true, (std::is_same< true_, is_detected> >())); EXPECT_EQ (true, (std::is_same< false_, is_detected> >())); EXPECT_EQ (true, (std::is_same< true_, is_detected> >())); EXPECT_EQ (true, (std::is_same< false_, is_detected> >())); EXPECT_EQ (true, (std::is_same< true_, is_detected> >())); EXPECT_EQ (true, (std::is_same< false_, is_detected> >())); EXPECT_EQ (true, (std::is_same< true_, is_detected> >())); EXPECT_EQ (true, (std::is_same< false_, is_detected> >())); EXPECT_EQ (true, (std::is_same< true_, is_detected >())); EXPECT_EQ (true, (std::is_same< false_, is_detected >())); EXPECT_EQ (true, (std::is_same< false_, is_detected >())); EXPECT_EQ (true, (is_detected_v>)); EXPECT_EQ (false,(is_detected_v>)); EXPECT_EQ (true, (is_detected_v)); } /* * Idiom */ TEST(TmetaDetection, Toolkit) { // detected_t EXPECT_EQ (true, (std::is_same< int, detected_t> >())); EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_none, A> >())); EXPECT_EQ (true, (std::is_same< A, detected_t< try_ctor1, A> >())); EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_ctor2, A> >())); EXPECT_EQ (true, (std::is_same< A&,detected_t< try_ppT, A> >())); EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_Tpp, A> >())); EXPECT_EQ (true, (std::is_same< int, detected_t< try_sfun, A> >())); EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_sfun, A> >())); EXPECT_EQ (true, (std::is_same< nat_, detected_t >())); EXPECT_EQ (true, (std::is_same< mFun, detected_t >())); // detected_or_t EXPECT_EQ (true, (std::is_same< int, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< Foo, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< A, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< void, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< A&,detected_or_t> >())); EXPECT_EQ (true, (std::is_same< nil_, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< int, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< void*, detected_or_t> >())); EXPECT_EQ (true, (std::is_same< nil_, detected_or_t >())); EXPECT_EQ (true, (std::is_same< mFun, detected_or_t >())); // is_detected_exact EXPECT_EQ (true, (std::is_same> >())); EXPECT_EQ (true, (std::is_same> >())); EXPECT_EQ (true, (std::is_same, try_ctor1, A> >())); EXPECT_EQ (true, (std::is_same, try_ctor2, A> >())); EXPECT_EQ (true, (std::is_same&,try_ppT, A> >())); EXPECT_EQ (true, (std::is_same&,try_Tpp, A> >())); EXPECT_EQ (true, (std::is_same> >())); EXPECT_EQ (true, (std::is_same> >())); EXPECT_EQ (true, (std::is_same, mFun, char, int> >())); EXPECT_EQ (true, (std::is_same, mFun, int> >())); // it would be better to check against mFun EXPECT_EQ (true, (is_detected_exact_v< int, try_type, A> )); EXPECT_EQ (false,(is_detected_exact_v< int, try_none, A> )); // is_detected_convertible EXPECT_EQ (true, (std::is_same> >())); EXPECT_EQ (true, (std::is_same> >())); EXPECT_EQ (true, (std::is_same, mFun, char, int> >())); EXPECT_EQ (true, (is_detected_convertible_v< int, try_type, A> )); EXPECT_EQ (false,(is_detected_convertible_v< int, try_none, A> )); } }