std::is_constructible, std::is_trivially_constructible, std::is_nothrow_constructible
Min standard notice:
Header: <type_traits>
- If T is an object or reference type and the variable definition T obj(std::declval
()…); is well-formed, provides the member constant value equal to true. In all other cases, value is false. For the purposes of this check, the variable definition is never interpreted as a function declaration, and the use of std::declval is not considered an odr-use. Access checks are performed as if from a context unrelated to T and any of the types in Args. Only the validity of the immediate context of the variable definition is considered.
# Declarations
template< class T, class... Args >
struct is_constructible;
(since C++11)
template< class T, class... Args >
struct is_trivially_constructible;
(since C++11)
template< class T, class... Args >
struct is_nothrow_constructible;
(since C++11)
# Notes
In many implementations, is_nothrow_constructible also checks if the destructor throws because it is effectively noexcept(T(arg)). Same applies to is_trivially_constructible, which, in these implementations, also requires that the destructor is trivial: GCC bug 51452 LWG issue 2116.
# Example
#include <iostream>
#include <type_traits>
class Foo
{
int v1;
double v2;
public:
Foo(int n) : v1(n), v2() {}
Foo(int n, double f) noexcept : v1(n), v2(f) {}
};
int main()
{
auto is = [](bool o) { return (o ? "\t" "is " : "\t" "isn't "); };
std::cout << "Foo ...\n"
<< is(std::is_trivially_constructible_v<Foo, const Foo&>)
<< "Trivially-constructible from const Foo&\n"
<< is(std::is_trivially_constructible_v<Foo, int>)
<< "Trivially-constructible from int\n"
<< is(std::is_constructible_v<Foo, int>)
<< "Constructible from int\n"
<< is(std::is_nothrow_constructible_v<Foo, int>)
<< "Nothrow-constructible from int\n"
<< is(std::is_nothrow_constructible_v<Foo, int, double>)
<< "Nothrow-constructible from int and double\n";
}