utl/test/tests/TmetaDetection.cpp
Christos Houtouridis bebb193278 DEV: minor changes
2019-11-14 12:24:04 +02:00

162 lines
7.5 KiB
C++

/*!
* \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 <http://www.gnu.org/licenses/>.
*
*/
#include <utl/meta/meta.h>
#include <gtest/gtest.h>
#include <type_traits>
namespace TmetaDetection {
using namespace utl;
using namespace meta;
/*
* Types to behave like Fixtures
*/
struct Foo {};
struct Bar {};
template <typename T> 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 <typename TT = T, typename = when<std::is_integral<TT>::type::value>>
TT sfun () { return TT{}; }
private:
int i_; double d_;
};
// A binary metafunction
template <typename T1, typename T2>
struct mFun {
using type = std::is_same <T1, T2>;
};
// detectors
template <typename T> using try_type = typename T::type;
template <typename T> using try_none = typename T::none;
template <typename T> using try_ctor1= decltype (T(std::declval<int>(), std::declval<double>()));
template <typename T> using try_ctor2= decltype (T(std::declval<int>()));
template <typename T> using try_ppT = decltype (++(std::declval<T>()));
template <typename T> using try_Tpp = decltype (std::declval<T>()++);
template <typename T> using try_sfun = decltype (std::declval<T>().sfun());
/*
* void_t
*/
TEST(TmetaDetection, VoidType) {
EXPECT_EQ(true, (std::is_same<void, void_t<int, long, void*, void, Foo, Bar>>()));
EXPECT_EQ(true, (std::is_same<void, void_t<>>()));
}
/*
* not a type
*/
TEST(TmetaDetection, NotAType) {
EXPECT_EQ(false, (std::is_default_constructible<nat_>()));
EXPECT_EQ(false, (std::is_destructible<nat_>()));
EXPECT_EQ(false, (std::is_copy_constructible<nat_>()));
EXPECT_EQ(false, (std::is_copy_assignable<nat_>()));
}
/*
* Idiom
*/
TEST(TmetaDetection, IsDetected) {
EXPECT_EQ (true, (std::is_same< true_, is_detected<try_type, A<int>> >()));
EXPECT_EQ (true, (std::is_same< false_, is_detected<try_none, A<int>> >()));
EXPECT_EQ (true, (std::is_same< true_, is_detected<try_ctor1, A<int>> >()));
EXPECT_EQ (true, (std::is_same< false_, is_detected<try_ctor2, A<int>> >()));
EXPECT_EQ (true, (std::is_same< true_, is_detected<try_ppT, A<int>> >()));
EXPECT_EQ (true, (std::is_same< false_, is_detected<try_Tpp, A<int>> >()));
EXPECT_EQ (true, (std::is_same< true_, is_detected<try_sfun, A<int>> >()));
EXPECT_EQ (true, (std::is_same< false_, is_detected<try_sfun, A<double>> >()));
EXPECT_EQ (true, (std::is_same< true_, is_detected<mFun, int, void> >()));
EXPECT_EQ (true, (std::is_same< false_, is_detected<mFun, char> >()));
EXPECT_EQ (true, (std::is_same< false_, is_detected<mFun, char, void, void> >()));
EXPECT_EQ (true, (is_detected_v<try_type, A<int>>));
EXPECT_EQ (false,(is_detected_v<try_none, A<int>>));
EXPECT_EQ (true, (is_detected_v<mFun, int, void>));
}
/*
* Idiom
*/
TEST(TmetaDetection, Toolkit) {
// detected_t
EXPECT_EQ (true, (std::is_same< int, detected_t<try_type, A<int>> >()));
EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_none, A<int>> >()));
EXPECT_EQ (true, (std::is_same< A<int>, detected_t< try_ctor1, A<int>> >()));
EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_ctor2, A<int>> >()));
EXPECT_EQ (true, (std::is_same< A<int>&,detected_t< try_ppT, A<int>> >()));
EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_Tpp, A<int>> >()));
EXPECT_EQ (true, (std::is_same< int, detected_t< try_sfun, A<int>> >()));
EXPECT_EQ (true, (std::is_same< nat_, detected_t< try_sfun, A<double>> >()));
EXPECT_EQ (true, (std::is_same< nat_, detected_t<mFun, void> >()));
EXPECT_EQ (true, (std::is_same< mFun<int, int>,
detected_t<mFun, int, int> >()));
// detected_or_t
EXPECT_EQ (true, (std::is_same< int, detected_or_t<Foo, try_type, A<int>> >()));
EXPECT_EQ (true, (std::is_same< Foo, detected_or_t<Foo, try_none, A<int>> >()));
EXPECT_EQ (true, (std::is_same< A<int>, detected_or_t<void, try_ctor1, A<int>> >()));
EXPECT_EQ (true, (std::is_same< void, detected_or_t<void, try_ctor2, A<int>> >()));
EXPECT_EQ (true, (std::is_same< A<int>&,detected_or_t<nil_, try_ppT, A<int>> >()));
EXPECT_EQ (true, (std::is_same< nil_, detected_or_t<nil_, try_Tpp, A<int>> >()));
EXPECT_EQ (true, (std::is_same< int, detected_or_t<void*, try_sfun, A<int>> >()));
EXPECT_EQ (true, (std::is_same< void*, detected_or_t<void*, try_sfun, A<double>> >()));
EXPECT_EQ (true, (std::is_same< nil_, detected_or_t<nil_, mFun, int> >()));
EXPECT_EQ (true, (std::is_same< mFun<char, int>,
detected_or_t<void, mFun, char, int> >()));
// is_detected_exact
EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< int, try_type, A<int>> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< int, try_none, A<int>> >()));
EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< A<int>, try_ctor1, A<int>> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< A<int>, try_ctor2, A<int>> >()));
EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< A<int>&,try_ppT, A<int>> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< A<int>&,try_Tpp, A<int>> >()));
EXPECT_EQ (true, (std::is_same<true_, is_detected_exact< int, try_sfun, A<int>> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_exact< int, try_sfun, A<double>> >()));
EXPECT_EQ (true, (std::is_same<true_, is_detected_exact<mFun<char, int>, mFun, char, int> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_exact<mFun<int, int>, mFun, int> >())); // it would be better to check against mFun<int>
EXPECT_EQ (true, (is_detected_exact_v< int, try_type, A<int>> ));
EXPECT_EQ (false,(is_detected_exact_v< int, try_none, A<int>> ));
// is_detected_convertible
EXPECT_EQ (true, (std::is_same<true_, is_detected_convertible< int, try_type, A<char>> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_convertible< int, try_none, A<int>> >()));
EXPECT_EQ (true, (std::is_same<false_, is_detected_convertible< mFun<int, int>, mFun, char, int> >()));
EXPECT_EQ (true, (is_detected_convertible_v< int, try_type, A<char>> ));
EXPECT_EQ (false,(is_detected_convertible_v< int, try_none, A<int>> ));
}
}