2

C++17 中 CTAD(类模板参数推导)鲜为人知的特性:您可以将用户定义的推导指南标记为explicit. (神箭。

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

A因此,类模板B具有明显不同的行为。我想编写一个单元测试,static_assert我的一个模板的行为类似于B,而不是A

static_assert(!has_properly_explicit_deduction_guide_v<A>);
static_assert(has_properly_explicit_deduction_guide_v<B>);

这在 C++17 和/或 C++20 和/或“C++future”中是否可行?

4

2 回答 2

3

不。

你不能检查声明,所以你不能检查A a = 1;or的有效性B b = 1;

并且类模板参数推导在任何其他复制初始化上下文中都无效。因此,虽然您可以通过查看表达式[](To){}(from)是否有效来检查“隐式可转换”,但您不能通过查看表达式是否有效来检查“隐式类模板参数推导” [](A){}(1),因为您不能只写A在那里。

您唯一可以检查的是是否A(1)有效,但那是直接初始化,因此无法验证explicit

于 2021-08-12T14:40:07.433 回答
0

目前,根据[dcl.type.class.deduct],推导的类类型的占位符可以出现在:

  • 变量的初始化声明;
  • 一个新的表达式
  • 显式类型转换(功能符号);或者
  • 非类型模板参数 [NTTP]。

其中第一个不是 SFINAE-able (无论是经典的还是在requires子句中),因为它是一个声明而不是一个表达式;接下来的两个调用直接初始化,而不是复制初始化;最后一个仅适用于具有constexpr构造函数的结构类型(尽管这在标准中并不是特别清楚)。

wrt。未来的方向,早在 2018 年,Mike Spertus 就在函数模板参数上寻找 CTAD:使用类模板参数推导改进函数模板如何使用类模板参数推导使简洁符号飙升。从那以后,这方面没有太多动静,但也许它可以复活。

于 2021-08-20T09:43:03.543 回答