【问题标题】:GCC 7 compilation error when using std::addressof使用 std::addressof 时出现 GCC 7 编译错误
【发布时间】:2017-08-14 08:33:46
【问题描述】:

我观察到一些我自己无法完全解释的奇怪行为。 代码如下所示:

#include <memory>
#include <vector>
#include <algorithm>

int main(){
    std::vector<double> t1(10, 5.0);
    std::vector<double*> t2(10);
    std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
    //std::transform(t1.begin(), t1.end(), t2.begin(), [](double& a){return &a;});
}

这里有一个与https://godbolt.org/g/YcNdbf 一起玩的版本 问题是这段代码使用 gcc4.9-6.3 编译得很好,但在 gcc 7.1 下编译失败。 Clang 也不喜欢。

(编辑)来自 gcc 7.1 的错误消息:

<source>: In function 'int main()':
8 : <source>:8:76: error: no matching function for call to 'transform(std::vector<double>::iterator, std::vector<double>::iterator, std::vector<double*>::iterator, <unresolved overloaded function type>)'
     std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
                                                                            ^
In file included from /opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/algorithm:62:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4281:5: note: candidate: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
     transform(_InputIterator __first, _InputIterator __last,
     ^~~~~~~~~
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4281:5: note:   template argument deduction/substitution failed:
8 : <source>:8:76: note:   could not resolve address from overloaded function 'addressof<double>'
     std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
                                                                            ^
In file included from /opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/algorithm:62:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4318:5: note: candidate: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
     transform(_InputIterator1 __first1, _InputIterator1 __last1,
     ^~~~~~~~~
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4318:5: note:   template argument deduction/substitution failed:
8 : <source>:8:76: note:   could not resolve address from overloaded function 'addressof<double>'
     std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
                                                                            ^
Compiler exited with result code 1

但是,我不太明白为什么它不起作用。

提前感谢任何试图提供帮助的人:)

【问题讨论】:

  • 请比“失败”和“不喜欢”更具体。包括逐字错误消息。
  • addressof 采用变量名而不是类型名
  • 对不起,我认为在 Godbolt 中查看它更容易,但我想你是对的,在这里也有它们是有意义的,所以我添加了它们;) | @meowgoesthedog 不确定你的意思,变量通过转换传递给函数,只需要指定模板参数对吗?
  • 将函数先存储在本地会发生什么?自动 f = std::addressof;

标签: c++ gcc std gcc7


【解决方案1】:

为避免意外获取临时地址,图书馆为addressof 获得了第二个(已删除)签名:

template <class T> constexpr T* addressof(T& r) noexcept;
template <class T> const T* addressof(const T&& elem) = delete;

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2598

所以现在编译器不知道你的代码是否应该匹配被删除的函数......

【讨论】:

  • 哦,哇,我以某种方式假设这些已删除的重载不会参与重载解决方案...非常感谢您的回答!这意味着除了将该调用包装在 lambda 中之外,我别无选择,对吧?
  • @Christoph 删除的重载专门用于参与重载解析,并为每个将解析给它们的函数调用提供编译时错误。否则它们将完全没用。
  • @Revolver_Ocelot 感谢您的解释:) 这对我来说完全有道理,我想我从来没有有意识地建立这种联系:P
  • @Christoph 同样,除了在 lambda 中包装调用之外,您还可以通过转换为具有指定签名的函数的指针来明确使用哪个重载:godbolt.org/g/UshjQS
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 2015-12-27
  • 2016-06-30
相关资源
最近更新 更多