gpt4 book ai didi

c++ - ADL 没有找到模板化的自由函数

转载 作者:行者123 更新时间:2023-11-28 04:26:36 28 4
gpt4 key购买 nike

我试图了解如何 ADL至少它的基础是有效的,并创建了以下代码:

#include <iostream>
#include <string>
#include <vector>

using std::pair;
using std::string;
using std::vector;

namespace My {
using std::to_string;

/** With these forward declarations it works ...
string to_string(char arg);
const string& to_string(const string& str);
template <typename T>
string to_string(const vector<T>& rhs);
template <typename T1, typename T2>
string to_string(const pair<T1, T2>& rhs);
struct A;
string to_string(const A& rhs);
*/

string to_string(char arg)
{
return string(1, arg);
}

const string& to_string(const string& str)
{
return str;
}

template <typename T>
string to_string(const vector<T>& rhs)
{
string str("");
for (const auto& e : rhs) {
str += to_string(e) + " "; //< this fails with `pair<..>`
/// `(to_string)(e)` would fail even with `A`
}
return str;
}

template <typename T1, typename T2>
string to_string(const pair<T1, T2>& rhs)
{
return to_string(rhs.first) + " " + to_string(rhs.second);
}

struct A {
static int counter;
string to_string() const
{
using My::to_string; //< avoid using `A::to_string`
return to_string("<A>[") + to_string(counter++) + to_string("]");
}
};
int A::counter = 0;

string to_string(const A& rhs)
{
return rhs.to_string();
}
}

int main(int /*argc*/, const char* /*argv*/[])
{
using My::to_string;
using My::A;
using std::cout;
using std::endl;

cout << to_string(3.1415) << endl;
cout << to_string(pair<int, char>{5, 'a'}) << endl;
cout << to_string(pair<double, pair<int, int>>{3.14, {1, 2}}) << endl;
cout << to_string(vector<int>{1, 2, 3}) << endl;
cout << to_string(pair<string, vector<int>>{"key", {1, 2, 3}}) << endl;
cout << to_string(pair<string, A>{"key", {}}) << endl;
cout << to_string(vector<A>{{}, {}, {}}) << endl;
/// this will fail to compile
cout << to_string(vector<pair<string, int>>{{"a", 1}, {"b", 2}}) << endl;

return 0;
}

我想通了,在 My 里面, using std::to_string将使用 std::免费功能(如果存在)并将使用 My::否则。然后,在命名空间之外 My , 做 using My::to_string 就足够了涵盖这两种情况。到目前为止还不错。

然后我在成员函数 A::to_string 中使用了相同的技术避免更喜欢函数本身而不是自由函数(这同样适用于任何其他成员函数)。

最后,我有点惊讶to_string(vector<A>)编译,尽管 A不是前向声明的。据我了解,这就是 ADL 发挥作用的地方。禁用它(将 to_string 括在方括号中)将导致编译失败。

长话短说之后,我的问题来了:为什么 ADL 在这种情况下对模板函数不起作用,即 to_string(pair<T1, T2>) ?更重要的是,如何修复它?如果没有必要执行前向声明,我会很高兴,因为在我的用例中 to_string(vector<T>) 的定义位于一些基本头文件中,后面的定义在不同的头文件中,此时不应该知道。

编辑:

我试图通过某些模板或什至某些 SFINAE 以某种方式“伪造”需要的前向声明,但这要么导致歧义,要么导致相同的结果。最后,我想出了使用成员函数的解决方案 to_string (但它可以是任何其他名称)所需的类。如果与 to_string 兼容,则需要始终实现此功能是需要的,在 STL 容器的情况下需要继承它们并添加成员函数。但我相信在这种情况下 ADL 永远不会失败。

修改部分代码:

template <typename T,
typename Fun = decltype(&T::to_string),
typename = std::enable_if_t<
std::is_member_function_pointer<Fun>::value>>
string to_string(const T& rhs)
{
return rhs.to_string();
}

template <typename T>
struct Vector : public vector<T> {
using vector<T>::vector;

string to_string() const
{
using My::to_string; //< avoid using `Vector::to_string`
string str("");
for (const auto& e : *this) {
str += to_string(e) + " ";
}
return str;
}
};

template <typename T1, typename T2>
struct Pair : public pair<T1, T2> {
using pair<T1, T2>::pair;

string to_string() const
{
using My::to_string; //< avoid using `Pair::to_string`
return to_string(this->first) + " " + to_string(this->second);
}
};

但是,必须替换 vector s 和 pairVector s 和 Pair秒。 (不再需要免费功能 to_string(A))。

其他解决方案,意见?

最佳答案

why ADL does not work in this case for templated function, i.e. to_string(pair<T1, T2>)?

ADL 通过检查与给定调用中涉及的类型关联的 namespace 来工作。然后它将考虑在这些命名空间中找到的适当重载并选择最佳的重载。

to_string(vector<pair<string, int>>{{"a", 1}, {"b", 2}})

此调用将选择重载 My::to_string(const vector<T>&)这依次调用 to_string(std::pair<std::string, int>) .

ADL 然后检查与 std::pair 关联的命名空间, std::stringint寻找过载 to_string(std::pair<...>) .由于在命名空间 std 中没有定义此类重载它需要找到调用之前的定义,但是重载 My::to_string(const pair<T1, T2>&)之后定义。这就是为什么您需要转发声明它。

注意你需要转发声明它因为你还有这个:

to_string(pair<string, vector<int>>)

另一方面,如果您有类似的东西:

to_string(vector<pair<string, My::A>>{{"a", {}}, {"b", {}}})

然后,调用的关联命名空间之一将是 My本身和过载 to_string(std::pair<...>)无需转发声明即可被发现。

关于c++ - ADL 没有找到模板化的自由函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54174729/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com