/*! Copyright (c) 2016 Barrett Adair Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #include #include #ifndef CT_ASSERT #define CT_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) #endif //CT_ASSERT namespace ct = callable_traits; namespace test1 { struct A1 { int operator()() const { return 0; } }; struct A2 { int operator()(int) const { return 0; } }; struct A3 { constexpr int operator()(int) const { return 0; } int operator()() const { return 0; } }; CT_ASSERT(!ct::is_constexpr(A1{})); CT_ASSERT(!ct::is_constexpr()); CT_ASSERT(!ct::is_constexpr(A2{})); CT_ASSERT(!ct::is_constexpr()); CT_ASSERT(!ct::is_constexpr(A3{})); CT_ASSERT(!ct::is_constexpr()); using A1_pmf = std::integral_constant; using A2_pmf = std::integral_constant; CT_ASSERT(!ct::is_constexpr(A1_pmf{})); CT_ASSERT(!ct::is_constexpr()); CT_ASSERT(!ct::is_constexpr(A2_pmf{})); CT_ASSERT(!ct::is_constexpr()); } namespace test2 { struct B1 { constexpr int operator()(int) const { return 1; } constexpr int operator()() const { return 1; } }; struct B2 { constexpr int operator()() const { return 1; } }; struct B3 { constexpr int operator()(int&) const { return 1; } }; struct B4 { constexpr int operator()(int&&) const { return 1; } }; struct B5 { constexpr int operator()(const int&) const { return 1; } }; struct B6 { constexpr int operator()(int) const { return 1; } }; struct B7 { constexpr int operator()(int, int, int, int, int, int, int, int, int, int) const & { return 1; } }; CT_ASSERT(ct::is_constexpr(B1{})); CT_ASSERT(ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(B2{})); CT_ASSERT(ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(B3{})); CT_ASSERT(ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(B4{})); CT_ASSERT(ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(B5{})); CT_ASSERT(ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(B6{})); CT_ASSERT(ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(B7{})); CT_ASSERT(ct::is_constexpr()); } namespace test3 { struct foo { constexpr int bar(int) const { return 1; } }; using C = std::integral_constant; CT_ASSERT(ct::is_constexpr(C{})); CT_ASSERT(ct::is_constexpr()); } namespace test4 { constexpr int foo(const int&) { return 1; } using D = std::integral_constant; CT_ASSERT(ct::is_constexpr(D{})); CT_ASSERT(ct::is_constexpr()); } namespace test5 { struct foo { static constexpr int value = 1; }; using E = std::integral_constant; //false because &foo::value is not a pointer to member data... it's static CT_ASSERT(!ct::is_constexpr(E{})); CT_ASSERT(!ct::is_constexpr()); } namespace test6 { struct foo { int value; }; using F = std::integral_constant; CT_ASSERT(!ct::is_constexpr(F{})); CT_ASSERT(!ct::is_constexpr()); } namespace test7 { // testing mixed constexpr overloads struct G1 { int operator()() const { return 1; } constexpr int operator()(int) const { return 1; } }; struct G2 { constexpr int operator()() const { return 1; } int operator()(int) const { return 1; } }; struct G3 { constexpr int operator()(char) const { return 1; } constexpr int operator()(int) const { return 1; } }; // we determine constexpr-ness by looking at overloads // with the fewest args first, so the overload with no // args is the determining member function CT_ASSERT(!ct::is_constexpr(G1{})); CT_ASSERT(!ct::is_constexpr()); CT_ASSERT(ct::is_constexpr(G2{})); CT_ASSERT(ct::is_constexpr()); // we can't resolve the overload in G3, due to the way // callable_traits::detail::any_arg_evaluated works CT_ASSERT(!ct::is_constexpr(G3{})); CT_ASSERT(!ct::is_constexpr()); } int main() { return 0; }