std::is_constructible无法给出正确的结果

8

源自于 这个 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>不能编译时,为什么std::is_constructible<aggregate_wrapper<foo_t>>::value会为真?

也许你在心理上混淆了“可构造的”和“默认可构造的”?一个aggregate_wrapper<foo_t>肯定可以被构造,只是不能通过aggregate_wrapper<foo_t> v;这种方式。 - M.M
@M.M 不对,is_default_constructible<T>is_constructible<T>(这意味着 Args... 是一个空包)是等价的。 - T.C.
不确定为什么这个被重新打开了;重复问题直接就是问题的关键。 - T.C.
@T.C.:纯属意外! - ildjarn
1个回答

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

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

然后有一个解释它的注释:

初始化的评估可能会导致副作用,例如类模板特化和函数模板特化的实例化,隐式定义函数的生成等。这些副作用不在直接上下文中,可能导致程序不合法。

我的理解是,当您编写以下内容时:
aggregate_wrapper<foo_t> v;

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

那我想std::is_constructible也没什么用了。我更愿意自己编写一个超越这个立即上下文的构造函数。 - Lingxi
зңҹжӯЈзҡ„й—®йўҳеә”иҜҘжҳҜдёәд»Җд№Ҳstd::is_constructibleдјҡеҒңз•ҷеңЁвҖңзӣҙжҺҘдёҠдёӢж–ҮвҖқпјҹ - Lingxi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接