为啥不能从 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<int>
作为参数传递给模板函数时,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
模板参数将是模棱两可的。但是,编译器不需要推断T
在std::addressof<int>
中的含义,除非这里有歧义。
这是我期望的一个工作示例(在 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<int>
推导出std::transform
s 模板参数?
【问题讨论】:
【参考方案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 有啥风险吗?