【问题标题】:Cannot use a constant reference of experimental::optional when using clang & libstdc++使用 clang 和 libstdc++ 时不能使用实验性::可选的常量引用
【发布时间】:2016-12-05 21:37:27
【问题描述】:

我正在对一个实验性的::optional 变量进行常量引用,但是当我在其上使用 operator->() 时,我有一个编译错误,但仅在使用 clang++ libstdc++时。

#include <experimental/optional>
#include <iostream>
#include <vector>

int main(void)
{
    std::experimental::optional<std::vector<int>> opt;
    const auto &rf = opt;

    opt.emplace();
    opt->push_back(1);

    std::cout << "opt->size() = " << opt->size()
              << " rf->size() = " << rf->size() << "\n";

    return 0;
}

运行这个程序:

$ clang++ -W -Wall -std=c++14 -stdlib=libc++ test.cc && ./a.out
opt->size() = 1 rf->size() = 1  # OK

$ g++ -W -Wall -std=c++14 test.cc && ./a.out
opt->size() = 1 rf->size() = 1  # OK

$ clang++ -W -Wall -std=c++14 test.cc
In file included from test.cc:1:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/optional:576:16: error: call to '__constexpr_addressof' is ambiguous
      { return __constexpr_addressof(this->_M_get()); }
               ^~~~~~~~~~~~~~~~~~~~~
test.cc:14:40: note: in instantiation of member function 'std::experimental::fundamentals_v1::optional<std::vector<int, std::allocator<int> > >::operator->' requested here
              << " rf->size() = " << rf->size() << "\n";
                                       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/optional:173:20: note: candidate function [with _Tp = const std::vector<int, std::allocator<int> >, $1 = <>]
    constexpr _Tp* __constexpr_addressof(_Tp& __t)
                   ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/optional:180:17: note: candidate function [with _Tp = const std::vector<int, std::allocator<int> >, $1 = <>]
    inline _Tp* __constexpr_addressof(_Tp& __t)
                ^
1 error generated.

每当我使用常量引用时都会出现此错误:显然非常量引用是可以的。

我将 Linux Mint 18 与这些版本的 g++/libstdc++ 5.4.0 和 clang++ 3.8.0 一起使用:

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ dpkg-query -s libstdc++-5-dev
...
Version: 5.4.0-6ubuntu1~16.04.4
...

$ clang++ --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

这是我的程序、libstdc++ 或 clang++ 中的错误吗?

更新:clang 3.9.0 解决了这个问题。 (正如下面 Richard Smith 和 Ville Voutilainen 所解释的,似乎 libstdc++ 期望编译器以某种与 clang 3.8.0 不匹配的方式运行。)

【问题讨论】:

    标签: c++ stl c++14 clang++ libstdc++


    【解决方案1】:

    这在我看来肯定是个错误,因为它诊断为不明确的重载具有互斥的 enable_if 约束,因此它们不应该是不明确的。

    【讨论】:

    • __constexpr_addressof 上的 SFINAE 条件要求编译器替换为展开为零元素的包。标准未指定该行为(以及一般扩展和替换的相对顺序)。
    • 啊,变态。这个问题当然可以在 libstdc++ 中避免。
    • FWIW,我安装了 clang 3.9.0 并且问题消失了,这对我来说已经足够好了。 :) 感谢您的回答!
    • 好吧,无论如何,我会看看我是否可以在 libstdc++ 中解决问题,一直回到 gcc 5:gcc.gnu.org/ml/gcc-patches/2016-12/msg00419.html
    • 作为历史参考,clang 中的行为已更改:llvm.org/bugs/show_bug.cgi?id=23840
    猜你喜欢
    • 1970-01-01
    • 2017-03-22
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    相关资源
    最近更新 更多