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

Lin*_*gxi 7 c++ type-traits language-lawyer template-meta-programming c++14

源自 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
}
Run Code Online (Sandbox Code Playgroud)

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

rod*_*igo 3

在 C++ 标准的is_constructible描述中,有这样一段看似无辜的引用:

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

然后是解释其含义的注释:

初始化的评估可能会导致副作用,例如类模板专业化和函数模板专业化的实例化、隐式定义函数的生成等。此类副作用不在直接上下文中,并且可能导致程序格式错误。

我的解释是,当你写:

aggregate_wrapper<foo_t> v;
Run Code Online (Sandbox Code Playgroud)

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