加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 在模板中执行参数依赖名称查找时的奇怪行为

发布时间:2020-12-16 05:06:26 所属栏目:百科 来源:网络整理
导读:最近,我正在研究模板类中名称的众所周知的“两阶段名称查找”的确切含义.虽然我已经阅读了很多关于此的文章,但我仍然无法了解这一切.现在我对下面显示的代码感到困惑: templatetypename Tclass A{public: void f(T,T){};};namespace ns{ typedef int TT; vo
最近,我正在研究模板类中名称的众所周知的“两阶段名称查找”的确切含义.虽然我已经阅读了很多关于此的文章,但我仍然无法了解这一切.现在我对下面显示的代码感到困惑:
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,int){};
};

template<typename T>
class B : public A<T> // note the base class is dependent
{
public:
    void g()
    {
        //f(T(),T()); // and this?
    }
};

由于基类是相关的,因此在非限定查找期间不会搜索它.因此,可以使用参数依赖查找找到f.您正确地声明f将仅在“第二阶段”(在实例化时)搜索,如在您的调用中,至少一个参数依赖于模板参数.

但是,ns不是依赖名称,也不是TT(在ns :: TT中).因此,名称空间和TT必须在它们用于g的定义之前声明.

无论是编写f(ns :: TT(),T())还是f(T(),T())都不会影响在参数依赖查找期间搜索f的一般规则:只有关联的命名空间和类参数的类型(T和ns :: TT).两者都是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();
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读