gpt4 book ai didi

c++ - 在模板中执行参数相关名称查找时的奇怪行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:39:46 26 4
gpt4 key购买 nike

最近我正在研究模板类中名称的著名“两阶段名称查找”的确切含义。虽然我已经阅读了很多这方面的文章,但我仍然无法对此一无所知。现在我对下面显示的代码感到困惑:

template<typename T>
class A
{
public:
void f(T, T){};
};

namespace ns
{
typedef int TT;
void f(int, int){};
};

template<typename T>
class B : public A<T>
{
public:
void g()
{

//f(T(), T()); // it's fine for error here
typedef ns::TT TTT;
f(TTT(), T()); // why this issued an error?
f(ns::TT(), T()); // and this?
}
};

/* I also think it's OK to move ns here */
// namespace ns
// {
// typedef int TT;
// void f(int, int){};
//};

int main()
{
B<int> b;
b.g();
}

请注意第二条评论。由于“f”是一个从属名称,它的查找应该延迟到“main”函数中的实例化。那时,编译器应该在 main 函数的范围内执行参数依赖名称查找。我想现在它应该发现命名空间 ns 中的函数,但它仍然发出编译错误:

1.cpp: In instantiation of 'void B<T>::g() [with T = int]':
1.cpp:30:6: required from here
1.cpp:23:15: error: 'f' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive] f(TTT(), T()); //why this issued an error?
^
1.cpp:23:15: note: declarations in dependent base 'A<int>' are not found by unqualified lookup
1.cpp:23:15: note: use 'this->f' instead

有人能给我解释一下吗?谢谢。

最佳答案

依赖于参数的查找仅搜索参数类型的关联类和命名空间。 typedef 只是一个透明的别名,类似于 using 声明。

来自标准 n3485 草案,[basic.lookup.argdep]/2 关于参数依赖查找:

For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set.

[强调我的]


template<typename T>
class A
{
public:
void f(T, T){};
};

namespace ns
{
typedef int TT;
void f(int, int){};
};

template<typename T>
class B : public A<T> // note the base class is dependent
{
public:
void g()
{
//f(T(), T()); // it's fine for error here
typedef ns::TT TTT;
f(TTT(), T()); // why this issued an error?
f(ns::TT(), T()); // and this?
}
};

由于基类是依赖的,非限定查找时不会查找。因此,f可以使用依赖于参数的查找找到。你正确地说 f将仅在“第二阶段”(在实例化时)搜索,就像在您的调用中一样,至少有一个参数依赖于模板参数。

然而,ns 不是从属名称,以及TT (在 ns::TT 中)。因此,命名空间和 TT必须在它们用于 g 的定义之前声明.

是否写f(ns::TT(), T())f(T(), T())不影响 f 的一般规则在依赖于参数的查找期间搜索:仅关联的 namespace 和参数类型的类(Tns::TT )。两者都是 int s B<int>::g() ,因此没有关联的类和命名空间。

f(TTT(), TTT())f 范围内更改查找现在是在名字查找阶段查找(它不是从属名称)。


这是一个参数依赖查找的例子:

namespace ns
{
struct TT {};
void f(TT, TT) {}
}

int main()
{
ns::TT x;
f(x, x);
}

现在,您也可以在类模板的成员函数中执行此操作:

namespace ns
{
struct TT {};
void f(TT, TT) {}
}

template<typename T>
struct B
{
void g()
{
f(T(), T());
}
};

int main()
{
B<ns::TT> x;
x.g();
}

但是,正如我所说,依赖于参数的名称查找不适用于基本类型,例如 int .

在上面的例子中,f再次依赖,因为至少有一个参数依赖于模板参数。因此,您也可以这样写:

template<typename T>
struct B
{
void g()
{
f(T(), T()); // looked up during the second phase,
// from the point of instantiation
}
};

namespace ns
{
struct TT {};
void f(TT, TT) {}
}

int main()
{
B<ns::TT> x;
x.g();
}

关于c++ - 在模板中执行参数相关名称查找时的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20924599/

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