为啥不能从 std::addressof<int> 解析模板参数?

Posted

技术标签:

【中文标题】为啥不能从 std::addressof<int> 解析模板参数?【英文标题】:Why can't template argument be resolved from std::addressof<int>?为什么不能从 std::addressof<int> 解析模板参数? 【发布时间】:2017-09-12 19:23:26 【问题描述】:

当模板参数std::addressof&lt;int&gt; 作为参数传递给模板函数时,Clang 和 GCC(MSVC 除外)无法解析模板参数。以下是此类错误的示例:

std::vector<int> v1,2,3,4,5;
std::vector<int*> pv(iv.size());
std::transform(v.begin(), v.end(), pv.begin(), std::addressof<int>);

叮当声:

<source>:8:5: error: no matching function for call to 'transform'
    std::transform(iv.begin(), iv.end(), piv.begin(), std::addressof<int>);
    ^~~~~~~~~~~~~~
/opt/compiler-explorer/clang-5.0.0/bin/../include/c++/v1/algorithm:2028:1: note: candidate template ignored: couldn't infer template argument '_UnaryOperation'
transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op)
^

海合会:

/opt/compiler-explorer/gcc-7.2.0/include/c++/7.2.0/bits/stl_algo.h:4295:5: note:   template argument deduction/substitution failed:
<source>:8:74: note:   could not resolve address from overloaded function 'addressof<int>'
     std::transform(iv.begin(), iv.end(), piv.begin(), std::addressof<int>);
                                                                          ^

如果参数是std::addressof,则该错误是有意义的,因为UnaryOperator 模板参数将是模棱两可的。但是,编译器不需要推断Tstd::addressof&lt;int&gt; 中的含义,除非这里有歧义。

这是我期望的一个工作示例(在 Clang 5 和 GCC 7.2 上编译):

template <typename T>
T* addrof(T& a)

    return __builtin_addressof(a);  


template <typename F, typename T>
void foo(F f, T& a)

    f(a);


int main()

    int a = 42;
    foo(addrof<int>, a);

我的疑问是:为什么不能从std::addressof&lt;int&gt; 推导出std::transforms 模板参数?

【问题讨论】:

【参考方案1】:

是的,它在您的示例中不起作用,因为自 C++ 17 以来,每个模板 std::addressof 都有两个重载(一个获取地址,另一个获取右值引用的已删除版本),并且对于编译器来说是模棱两可的选择哪一个。最简单的解决方案是使用 lambda:

#include <vector>
#include <algorithm>

void foo() 
   std::vector<int> v1,2,3,4,5;
   std::vector<int*> pv(v.size());
   std::transform(v.begin(), v.end(), pv.begin(), 
                  [](int& i)  return std::addressof(i););

这里列出了这些重载:http://en.cppreference.com/w/cpp/memory/addressof

另一种选择是使用强制转换,但它很丑,而且你应该更喜欢 Lambda!尽管如此,将提供完整性:

#include <vector>
#include <algorithm>

void foo() 
   std::vector<int> v1,2,3,4,5;
   std::vector<int*> pv(v.size());

   std::transform(v.begin(), v.end(), pv.begin(), 
                  static_cast<int* (*)(int&) >(std::addressof<int>));

【讨论】:

你知道哪个提案改变了这一点吗?

以上是关于为啥不能从 std::addressof<int> 解析模板参数?的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::addressof(std::cout) 代替 &std::cout 有啥风险吗?

为啥 innerHTML 在 for 循环中不能正常工作?

C语言程序错误 为啥OXFFFFFF的内存不能written 编译没有问题啊 请问为啥啊

为啥全局修饰符不能正常工作?

java ,为啥无法从静态上下文中引用非静态方法

为啥升序排序 C++ 不能正常工作?