Why does the following code not compile? The static assertion checks that Foo
is not copy assignable, so I would expect that the compiler discards the code in the constexpr-if block, but it doesn't.
#include <type_traits>
struct Foo {
Foo() = default;
Foo const& operator=(Foo const&) = delete;
};
int main()
{
static_assert(!std::is_copy_assignable_v<Foo>);
Foo x;
Foo other;
if constexpr (std::is_copy_assignable_v<Foo>) {
other = x;
}
return 0;
}
Compiler error:
<source>: In function 'int main()':
<source>:16:17: error: use of deleted function 'const Foo& Foo::operator=(const Foo&)'
16 | other = x;
| ^
<source>:5:16: note: declared here
5 | Foo const& operator=(Foo const&) = delete;
| ^~~~~~~~
Compiler returned: 1
This code snippet
Foo x;
Foo other;
if constexpr (std::is_copy_assignable_v<Foo>) {
other = x;
}
is pesent in a non-template function. So the compiler checks the validaty of the code.
On the other hand, if you have a template code then the code that represents a substatement of the if constexpr statement will not be instantiated if the value of the expression of the if statement is evaluated to false.
Here is a demonstration program.
#include <iostream>
#include <type_traits>
struct Foo
{
Foo() = default;
Foo const &operator=( Foo const & ) = delete;
};
template <typename T>
void f( T &t )
{
if constexpr (std::is_copy_assignable_v<T>)
{
T t2;
t2 = t;
}
else
{
std::cout << "I'm not copy assignable.\n";
}
}
int main()
{
Foo foo;
f( foo );
}
The program output is
I'm not copy assignable.
From the C++20 Standard (8.5.1 The if statement):
2 If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool (7.7); this form is called a constexpr if statement. If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement. During the instantiation of an enclosing templated entity (13.1), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.