标签: dependent-name

我必须在何处以及为何要使用"模板"和"typename"关键字?

在模板,在那里,为什么我必须把typenametemplate上依赖的名字呢?究竟什么是依赖名称?我有以下代码:

template <typename T, typename Tail> // Tail will be a UnionNode too.
struct UnionNode : public Tail {
    // ...
    template<typename U> struct inUnion {
        // Q: where to add typename/template here?
        typedef Tail::inUnion<U> dummy; 
    };
    template< > struct inUnion<T> {
    };
};
template <typename T> // For the last node Tn.
struct UnionNode<T, void> {
    // ...
    template<typename U> struct inUnion {
        char fail[ -2 + (sizeof(U)%2) ]; // Cannot be instantiated for any …
Run Code Online (Sandbox Code Playgroud)

c++ templates c++-faq dependent-name typename

1061
推荐指数
8
解决办法
15万
查看次数

条件运算符的返回类型和两阶段查找

请考虑以下代码段:

struct Base { };
struct Derived : Base { };

void f(Base &) { std::cout << "f(Base&)\n"; }

template <class T = int>
void g() {
    Derived d;
    f(T{} ? d : d); // 1
}

void f(Derived &) { std::cout << "f(Derived&)\n"; }

int main() {
    g();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我认为应该在第一阶段查找对fat 的函数调用// 1,因为它的参数的类型是明确的Derived&,因此可以解析为f(Base&)范围中唯一的一个.

Clang 3.8.0同意我的观点,但是GCC 6.1.0没有,并推迟f到第二阶段的查找,在那里f(Derived&)被选中.

哪个编译器是对的?

c++ dependent-name language-lawyer compiler-bug name-lookup

39
推荐指数
2
解决办法
1085
查看次数

C++模板的两阶段名称查找 - 为什么?

为什么C++标准为模板定义了两个阶段查找?非依赖声明和定义的查找是否也可以推迟到实例化阶段?

c++ templates dependent-name name-lookup

27
推荐指数
1
解决办法
5002
查看次数

static_assert依赖于非类型模板参数(gcc和clang上的不同行为)

template <int answer> struct Hitchhiker {
  static_assert(sizeof(answer) != sizeof(answer), "Invalid answer");
};

template <> struct Hitchhiker<42> {};
Run Code Online (Sandbox Code Playgroud)

在尝试禁用常规模板实例化的同时,static_assert我发现clang即使模板未实例化,上面的代码也会生成断言错误,而gcc只有在Hitchhiker使用除了以外的参数进行实例化时才生成断言错误42.

摆弄我发现这个断言:

template <int answer> struct Hitchhiker {
  static_assert(sizeof(int[answer]) != sizeof(int[answer]), "Invalid answer");
};

template <> struct Hitchhiker<42> {};
Run Code Online (Sandbox Code Playgroud)

两个编译器的行为相同:只有在实例化通用模板时,断言才会启动.

标准说什么,哪个编译器是对的?

g++ 4.9.2
clang++ 3.50
Run Code Online (Sandbox Code Playgroud)

c++ templates dependent-name language-lawyer c++14

25
推荐指数
2
解决办法
1136
查看次数

g ++和MSVS之间的名称查找差异

考虑以下代码:

#include <iostream>

namespace N {
    class A {};
    void f(A a) { std::cout << "N::f\n"; }
}

void f(int i) { std::cout << "::f\n"; }

template <typename T>
class Base {
  public:
    void f(T x) { std::cout << "Base::f\n"; }
};


template <typename T>
class X : public Base<T> {
  public:
    void g() {
        T t;
        f(t);
    }
};

int main()
{
    X<N::A> x1;
    x1.g();

    X<int> x2;
    x2.g();
}
Run Code Online (Sandbox Code Playgroud)

该代码旨在研究名称查找在C++中的工作方式.

如果我用GNU C++(版本6.1.0)编译该程序,它会打印:

N::f
::f
Run Code Online (Sandbox Code Playgroud)

但如果我用Microsoft Visual Studio 2015编译它,它会打印:

Base::f …
Run Code Online (Sandbox Code Playgroud)

c++ templates base-class dependent-name name-lookup

20
推荐指数
2
解决办法
555
查看次数

Why does this template function not behave as expected?

I was reading about template functions and got confused by this problem:

#include <iostream>

void f(int) {
    std::cout << "f(int)\n";
}

template<typename T>
void g(T val) {
    std::cout << typeid(val).name() << "  ";
    f(val);
}

void f(double) {
    std::cout << "f(double)\n";
}

template void g<double>(double);

int main() {
    f(1.0); // f(double)
    f(1);   // f(int)
    g(1.0); // d  f(int), this is surprising
    g(1);   // i  f(int)
}
Run Code Online (Sandbox Code Playgroud)

The results are the same if I don't write template void g<double>(double);.

I …

c++ dependent-name function-templates name-lookup unqualified-name

17
推荐指数
2
解决办法
570
查看次数

调用模板基类的模板函数

可能重复:
我必须在何处以及为何要使用"template"和"typename"关键字?

这是代码:

template<typename T>
class base
{
public:
    virtual ~base();

    template<typename F>
    void foo()
    {
        std::cout << "base::foo<F>()" << std::endl;
    }
};

template<typename T>
class derived : public base<T>
{
public:
    void bar()
    {
        this->foo<int>(); // Compile error
    } 
};
Run Code Online (Sandbox Code Playgroud)

而且,在运行时:

derived<bool> d;
d.bar();
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

error: expected primary-expression before ‘int’
error: expected ‘;’ before ‘int’
Run Code Online (Sandbox Code Playgroud)

我知道非依赖名称和两阶段查找.但是,当函数本身是模板函数(foo<>()我的代码中的函数)时,我尝试了所有变通方法只是失败了.

c++ templates dependent-name

16
推荐指数
2
解决办法
2万
查看次数

允许`this->`访问依赖基类成员的规则是什么?

我们知道,下面的代码格式错误,因为该成员x位于依赖基类中.但是,更改xthis->x指示的行将修复错误.

template <typename T>
struct B {
    int x;
};
template <typename T>
struct C : B<T> {
    void f() {
        int y = x; // Error!
    }
};
int main() {
    C<int> c;
    c.f();
}
Run Code Online (Sandbox Code Playgroud)

我想解释一下标准中如何指定这种行为.根据[temp.dep]/3:

在类或类模板的定义中,如果基类依赖于模板参数,则在类模板或成员的定义点或在实例化实例化期间,不会在非限定名称查找期间检查基类作用域.类模板或成员.

这似乎解释了为什么x单独使用失败.x在定义点查找名称,不检查基类范围.但是,如果我们使用this->x怎么办?现在名称x是依赖的,其查找被推迟到实例化.但引用的段落似乎暗示即使在实例化时x也不应该找到,因为查找xin 仍然this->x不合格的查找.

显然,实现不会以这种方式运行,并且人们普遍认为,一旦模板被实例化,就会搜索基类范围.

  1. 我误解了引用的段落吗?
  2. 是否有一个段落指定"正确"的行为?

c++ templates dependent-name language-lawyer name-lookup

15
推荐指数
1
解决办法
284
查看次数

为什么数据成员的模板功能只有在用"this"限定时才是依赖名称?

struct Bar {
    template<typename>
    void baz() {
    }
};

template<typename>
struct Foo {
    Bar bar;

    Foo() {
        bar.baz<int>();
    }
};

int main() {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这段代码编译得很好(在GCC 4.7中),但如果我将调用前缀bar.baz<int>()加上this->,则baz成为需要消除歧义的从属名称template.

bar.baz<int>(); // OK
this->bar.baz<int>(); // error
this->bar.template baz<int>(); // OK
Run Code Online (Sandbox Code Playgroud)

当然this->bar只能参考Bar bar,其成员baz显然是模板?为什么添加this->使代码对编译器不明确?

ps最初,bar是一个需要消除歧义的基类模板的数据成员this->,但为了这个问题,我简化了示例.

c++ templates dependent-name c++11

14
推荐指数
1
解决办法
381
查看次数

模板基类typedef成员不可见

我知道默认情况下编译器不能看到"依赖名称".但是我在回答其他SO问题(这里,在这里,最终在C++ faq)时被告知using声明可能有所帮助.

所以我试过了.

模板基类:

// regardless of the fact that members are exposed...
template<typename T>
struct TBase {
   typedef T MemberType;
   MemberType baseMember;
   MemberType baseFunction() { return MemberType(); }
};
Run Code Online (Sandbox Code Playgroud)

和派生类,使用基数的成员:

template<typename T>
struct TDerived : public TBase<T> {
   // http://www.parashift.com/c++-faq-lite/nondependent-name-lookup-members.html
   // tells us to use a `using` declaration.
   using typename TBase<T>::MemberType;
   using TBase<T>::baseFunction;
   using TBase<T>::baseMember;

   void useBaseFunction() { 
      // this goes allright.
      baseFunction();
      ++baseMember;

      // but here, the compiler doesn't want …
Run Code Online (Sandbox Code Playgroud)

c++ templates typedef dependent-name

13
推荐指数
1
解决办法
3239
查看次数