【问题标题】:Should this code fail to compile in C++17?此代码是否应该无法在 C++17 中编译?
【发布时间】:2019-10-15 11:22:36
【问题描述】:

我正在更新一个项目以使用 C++17,并发现一些遵循此模式的代码在最新版本的 clang 上导致编译错误的情况:

#include <boost/variant.hpp>

struct vis : public boost::static_visitor<void>
{
    void operator()(int) const { }
};

int main()
{
    boost::variant<int> v = 0;
    boost::apply_visitor(vis{}, v);
}

Using clang v8.0 in C++17 mode, this fails with the following error:

<source>:11:30: error: temporary of type 'boost::static_visitor<void>' has protected destructor
    boost::apply_visitor(vis{}, v);
                             ^
/opt/compiler-explorer/libs/boost_1_64_0/boost/variant/static_visitor.hpp:53:5: note: declared protected here
    ~static_visitor() = default;

但是,it compiles cleanly in C++14 mode。我发现如果我将大括号初始化vis{} 更改为括号vis(),那么它在两种模式下都能正确编译。我尝试过的每个 gcc 版本都允许在 C++17 模式下使用这两种变体。

这是从 C++14 到 C++17 的正确行为变化,还是一个 clang 错误?如果它是正确的,为什么它现在在 C++17 中无效(或者它可能一直是,但 clang 只是在早期的标准版本中允许它)?

【问题讨论】:

  • 在 1.70 中提升 fixed 这个。还讨论了here

标签: c++ clang c++17 boost-variant


【解决方案1】:

clang 在这里是正确的。这是一个简化的示例:

struct B {
protected:
    B() { }
};

struct D : B { };

auto d = D{};

在 C++14 中,D不是聚合,因为它有一个基类,所以 D{} 是调用 D' 的“正常”(非聚合)初始化s 默认构造函数,它反过来调用B 的默认构造函数。这很好,因为D 可以访问B 的默认构造函数。

在 C++17 中,聚合的定义得到了扩展——现在允许基类(只要它们不是virtual)。 D 现在是一个聚合,这意味着 D{} 是聚合初始化。在聚合初始化中,这意味着我们(调用者)正在初始化所有子对象——包括基类子对象。但是我们确实没有可以访问B 的构造函数(它是protected),所以我们不能调用它,所以它是不正确的。


不要害怕,修复很容易。使用括号:

auto d = D();

这又像以前一样调用D 的默认构造函数。

【讨论】:

  • 完美,这就是我一直在寻找的:加宽的聚合定义是罪魁祸首。
  • clang 正确吗?子对象初始化器的可访问性上下文是什么?有一个核心语言问题:issue #2244。作为编码人员,我希望在这两种情况下,在聚合的上下文中完成对 dcl.init.aggr/5.1dcl.init.aggr/5.2 的名称可访问性检查。
  • 听说C++20中圆括号和大括号是统一的。这会影响修复的有效性吗?
  • @L.F.不,不是的。 D()value initializationnew bullet 之前。
  • 还原略有错误。 C++17 中的问题是 dtor(static_visitor 本身就是一个 C++17 聚合,因此 ctor 的保护性无关紧要)。在 C++20 中,两者都是问题,并且 boost 修复(仅修复了 dtor)将再次中断,这使其成为 C++20 OMG-these-contrived-examples-are-so-surprising-的一个很好的例子我们必须修复它,改变破坏性的东西。
猜你喜欢
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 2017-04-29
  • 2015-06-24
  • 1970-01-01
  • 2011-06-14
  • 2019-10-23
  • 2010-12-20
相关资源
最近更新 更多