/*!
* \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> ));
}
}