162 lines
7.5 KiB
C++
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>> ));
|
|
|
|
}
|
|
}
|