为什么 ADL 在依赖类型名上失败?

bit*_*ask 1 c++ argument-dependent-lookup

我注意到get<0>(t)无法解析std::get<0>(t)其参数类型是否依赖于模板参数:

template <typename T>
void foo(T) {
  std::tuple<T> tup{0};
  get<0>(tup) = 1; // error: 'get' was not declared in this scope; did you mean 'std::get'?
}
Run Code Online (Sandbox Code Playgroud)

foo如果不是模板(即如果tup声明为std::tuple<int>)或使用 ,则效果很好using std::get;。难道它不应该在 ADL 通常特别有用的函数模板中工作吗?

Art*_*yer 5

这在 C++20 ( P0846R0 ) 中进行了更改。

在 C++20 之前,get<0>(tup) = 1被解析为get < 0 > (tup) = 1(get 小于零大于 tup 赋值为 1)。由于get不存在,因此无法编译。

在 C++20 中,添加了一条新规则,因此当未找到任何内容时将其解释为模板名称,从而允许将其解释为调用函数模板。

C++20 之前的修复是在作用域中声明一个函数模板,即使它最终不会被选择:

// Make it difficult to call this by accident
template<template<template<int> class> class>
void get() = delete;

template <typename T>
void foo(T) {
  std::tuple<T> tup{0};
  // lookup for `get` finds the global function template, so this is
  // parsed as a call to a template function
  get<0>(tup) = 1;
}
Run Code Online (Sandbox Code Playgroud)