std::is_constructible 没有给出正确的结果

std::is_constructible doesn't give the correct result

本文关键字:结果 is constructible std      更新时间:2023-10-16

源自以下 CodeReview 主题:

#include <cstddef>
#include <algorithm>
#include <iostream>
#include <type_traits>
#include <utility>
template <typename T>
class aggregate_wrapper : public T {
private:
  using base = T;
public:
  using aggregate_type = T;
  template <typename... Ts>
  aggregate_wrapper(Ts&&... xs)
      : base{std::forward<Ts>(xs)...} {
    // nop
  }
};
struct foo_t {
  foo_t(int) {}  
};
int main() {
  std::cout << std::is_constructible<foo_t>::value << std::endl;
  std::cout << std::is_constructible<aggregate_wrapper<foo_t>>::value << std::endl;
  // aggregate_wrapper<foo_t> v; // won't compile
}

aggregate_wrapper<foo_t> v;实际上没有编译时,std::is_constructible<aggregate_wrapper<foo_t>>::value怎么可能是真的?

在C++标准中,在is_constructible描述中,有这样一句无辜的话:

只考虑 [虚v] 变量初始化的直接上下文的有效性。

然后是一个注释,解释它的含义:

初始化的评估可以导致 诸如类模板专用化和函数模板专用化的实例化等效果, 生成隐式定义的函数,依此类推。这种副作用不在直接上下文中,可能导致程序格式不正确。

我的解释是,当你写:

aggregate_wrapper<foo_t> v;

您正在使用默认构造函数 aggregate_wrapper ,它存在并且可访问,因此它成功了,至少在直接上下文中是这样。然后,非即时上下文包括构造函数的主体,并且失败,但这不会改变is_constructible的结果。