blob: 310addb91abb9fe4aae83d77d869f1207f8d3798 [file] [log] [blame]
// Copyright (C) 2016-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library 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 General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do compile { target c++17 } }
#include <type_traits>
#ifndef IS_NT_INVOCABLE_DEFINED
template<typename... T>
constexpr bool is_nt_invocable()
{
constexpr bool result = std::is_nothrow_invocable_v<T...>;
static_assert(std::is_nothrow_invocable<T...>::value == result);
return result;
}
template<typename R, typename... T>
constexpr bool is_nt_invocable_r()
{
constexpr bool result = std::is_nothrow_invocable_r_v<R, T...>;
static_assert(std::is_nothrow_invocable_r<R, T...>::value == result);
return result;
}
#endif
void test01()
{
struct T { T(int) { } };
struct NT { NT(int) noexcept { } };
struct Ex { explicit Ex(int) noexcept { } };
using func_type = void(*)();
static_assert( ! is_nt_invocable< func_type>(), "");
#if __cpp_noexcept_function_type
using func_type_nt = void(*)() noexcept;
static_assert( is_nt_invocable< func_type_nt >(), "");
#endif
struct X { };
using mem_type = int X::*;
static_assert( ! is_nt_invocable< mem_type >(), "");
static_assert( ! is_nt_invocable< mem_type, int >(), "");
static_assert( ! is_nt_invocable< mem_type, int& >(), "");
static_assert( is_nt_invocable< mem_type, X& >(), "");
static_assert( is_nt_invocable_r< int, mem_type, X& >(), "");
static_assert( is_nt_invocable_r< int&, mem_type, X& >(), "");
static_assert( is_nt_invocable_r< long, mem_type, X& >(), "");
static_assert( ! is_nt_invocable_r< long&, mem_type, X& >(),
"conversion fails, cannot bind long& to int");
static_assert( is_nt_invocable_r< int&, mem_type, X* >(), "");
static_assert( ! is_nt_invocable_r< T, mem_type, X& >(),
"conversion throws");
static_assert( is_nt_invocable_r< NT, mem_type, X& >(), "");
static_assert( ! is_nt_invocable_r< Ex, mem_type, X& >(),
"conversion fails, would use explicit constructor");
using memfun_type = int (X::*)();
static_assert( ! is_nt_invocable< memfun_type >(), "no object");
static_assert( ! is_nt_invocable< memfun_type, int >(), "no object");
static_assert( ! is_nt_invocable< memfun_type, int& >(), "no object");
static_assert( ! is_nt_invocable< memfun_type, X& >(), "call throws");
static_assert( ! is_nt_invocable< memfun_type, X* >(), "call throws");
static_assert( ! is_nt_invocable_r< T, memfun_type, X& >(), "call throws");
static_assert( ! is_nt_invocable_r< NT, memfun_type, X& >(), "call throws");
static_assert( ! is_nt_invocable_r< Ex, memfun_type, X& >(), "call throws");
#if __cpp_noexcept_function_type
using memfun_type_nt = int (X::*)() noexcept;
static_assert( ! is_nt_invocable< memfun_type_nt >(), "no object");
static_assert( ! is_nt_invocable< memfun_type_nt, int >(), "no object");
static_assert( ! is_nt_invocable< memfun_type_nt, int& >(), "no object");
static_assert( is_nt_invocable< memfun_type_nt, X& >(), "");
static_assert( is_nt_invocable< memfun_type_nt, X* >(), "");
static_assert( ! is_nt_invocable_r< T, memfun_type_nt, X& >(),
"conversion throws");
static_assert( is_nt_invocable_r< NT, memfun_type_nt, X& >(), "");
static_assert( ! is_nt_invocable_r< Ex, memfun_type_nt, X& >(),
"conversion fails, would use explicit constructor");
#endif
struct F {
int& operator()();
long& operator()() const noexcept;
short& operator()(int) &&;
char& operator()(int) const& noexcept;
private:
void operator()(int, int) noexcept;
};
using CF = const F;
static_assert( ! is_nt_invocable< F >(), "call throws");
static_assert( is_nt_invocable< CF >(), "");
static_assert( ! is_nt_invocable_r< int&, F >(), "call throws");
static_assert( is_nt_invocable_r< long&, CF >(), "");
static_assert( ! is_nt_invocable_r< T, F >(), "call throws");
static_assert( ! is_nt_invocable_r< NT, F >(), "call throws");
static_assert( ! is_nt_invocable_r< Ex, F >(), "call throws");
static_assert( ! is_nt_invocable_r< void, F >(), "call throws");
static_assert( ! is_nt_invocable_r< T, CF >(), "conversion throws");
static_assert( is_nt_invocable_r< NT, CF >(), "" );
static_assert( ! is_nt_invocable_r< Ex, CF >(), "conversion fails");
static_assert( is_nt_invocable_r< void, CF >(), "");
static_assert( ! is_nt_invocable< F, int >(), "call throws");
static_assert( is_nt_invocable< F&, int >(), "");
static_assert( ! is_nt_invocable_r< short&, F, int >(),
"call throws" );
static_assert( is_nt_invocable_r< char&, F&, int >(), "");
static_assert( ! is_nt_invocable_r< T, F&, int >(),
"conversion throws");
static_assert( is_nt_invocable_r< NT, F&, int >(), "");
static_assert( ! is_nt_invocable_r< Ex, F&, int >(),
"conversion fails, would use explicit constructor");
static_assert( is_nt_invocable< CF, int >(), "");
static_assert( is_nt_invocable< CF&, int >(), "");
static_assert( is_nt_invocable_r< char&, CF, int >(), "");
static_assert( is_nt_invocable_r< char&, CF&, int >(), "");
static_assert( is_nt_invocable_r< void, CF&, int >(), "");
static_assert( ! is_nt_invocable_r< T, CF&, int >(),
"conversion throws");
static_assert( is_nt_invocable_r< NT, CF&, int >(), "");
static_assert( ! is_nt_invocable_r< Ex, CF&, int >(),
"conversion fails, would use explicit constructor");
static_assert( is_nt_invocable_r< void, CF&, int >(), "");
static_assert( ! is_nt_invocable< F, int, int >(),
"would call private member");
static_assert( ! is_nt_invocable_r<void, F, int, int >(),
"would call private member");
struct FX {
X operator()() const noexcept { return {}; }
};
static_assert( is_nt_invocable< FX >(), "FX::operator() is nothrow" );
static_assert( is_nt_invocable_r<X, FX >(), "no conversion needed" );
static_assert( is_nt_invocable_r<void, FX >(), "" );
struct Y {
explicit Y(X) noexcept; // not viable for implicit conversions
Y(...);
};
static_assert( ! is_nt_invocable_r<Y, FX >(), "conversion to Y can throw" );
}