Reputation: 27290
Little-known feature of CTAD (class template argument deduction) in C++17: you can mark user-defined deduction guides as explicit
.
(Godbolt.)
template<class T> struct A { A(int); }; A(int) -> A<int>;
template<class T> struct B { B(int); }; explicit B(int) -> B<int>;
A<int> a = 1; // OK, constructor of A<int> is implicit
B<int> b = 1; // OK, constructor of B<int> is implicit
auto a = A(1); // OK, deduction guide of A exists
auto b = B(1); // OK, deduction guide of B exists
A a = 1; // OK, deduction guide of A is non-explicit
B b = 1; // ERROR!! deduction guide of B is explicit
So, class templates A
and B
have observably different behavior.
I'd like to write a unit test that static_assert
s that one of my templates behaves like B
, not like A
.
static_assert(!has_properly_explicit_deduction_guide_v<A>);
static_assert(has_properly_explicit_deduction_guide_v<B>);
Is this possible in C++17 and/or C++20 and/or "C++future"?
Upvotes: 2
Views: 387
Reputation: 157414
Currently, per [dcl.type.class.deduct], a placeholder for a deduced class type can appear in:
The first of these is not SFINAE-able (either classically or in a requires
clause), since it is a declaration and not an expression; the next two invoke direct-initialization, not copy-initialization; and the last only works for structural types with constexpr
constructors (although this isn't particularly clear from the Standard).
wrt. future direction, back in 2018 Mike Spertus was angling for CTAD on function template arguments: Improving function templates with Class Template Argument Deduction, How to make Terse Notation soar with Class Template Argument Deduction. There hasn't been much movement on this since then, but perhaps it could be resurrected.
Upvotes: 0
Reputation: 303337
No.
You can't check declarations, so you can't check the validity of A a = 1;
or B b = 1;
And class template argument deduction isn't valid in any other copy-initialization contexts. So while you can check "implicitly convertible" by seeing if the expression [](To){}(from)
is valid, you cannot check "implicitly class-template-argument-deducible" by seeing if the expression [](A){}(1)
is valid, since you cannot just write A
there.
The only thing that you can check is whether A(1)
is valid or not, but that is direct initialization, and so would not be able to validate explicit
ness.
Upvotes: 3