标签: dependent-name

模板基类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
查看次数

从依赖基类访问类型

有谁知道为什么使用声明似乎不适用于从依赖基类导入类型名称?它们适用于成员变量和函数,但至少在GCC 4.3中,它们似乎被忽略了类型.

template <class T>
struct Base
{
  typedef T value_type;
};

template <class T>
struct Derived : Base<T>
{
  // Version 1: error on conforming compilers
  value_type get();

  // Version 2: OK, but unwieldy for repeated references
  typename Base<T>::value_type get();

  // Version 3: OK, but unwieldy for many types or deep inheritance
  typedef typename Base<T>::value_type value_type;
  value_type get();

  // Version 4: why doesn't this work?
  using typename Base<T>::value_type;
  value_type get(); // GCC: `value_type' is not a type
};
Run Code Online (Sandbox Code Playgroud)

我有一个基类,有一组allocator样式的typedef,我想在几个继承级别继承.到目前为止,我发现的最佳解决方案是上面的版本3,但我很好奇为什么版本4似乎不起作用.GCC接受使用声明,但似乎忽略它. …

c++ templates dependent-name using-declaration

11
推荐指数
1
解决办法
3445
查看次数

为什么`this`是一个依赖于类型的表达式,即使模板类没有基类?

可以编译以下代码而不会出现错误:

template <typename T> struct A {
    void f() { this->whatever; } // whatever is not declared before
};
int main() {
    A<int> a;
}
Run Code Online (Sandbox Code Playgroud)

我知道这是因为this是一个依赖于类型的表达式,它使名称查找whatever被推迟,直到知道实际的模板参数.由于f()在这种情况下从不使用成员函数,因此不A<T>::f存在实例化,并且whatever永远不会执行名称查找.

我可以理解,this如果类模板具有依赖于类型的基类,那么它是类型相关的:

template <typename T> struct B { T whatever; };
template <typename T> struct A : B<T> {
    void f() { this->whatever; }
};
int main() {
    A<int> a;
}
Run Code Online (Sandbox Code Playgroud)

在解析模板类的定义时A,不可能知道它的基类是什么,这使得this->whatever潜在合法(B<T>可能有一个成员命名whatever).相反,this->whatever一旦在f …

c++ templates dependent-name

11
推荐指数
1
解决办法
285
查看次数

多个嵌套的依赖名称 - 在哪里粘贴typename关键字?

这个问题的灵感来自另一个问题.在尝试回答这个问题时,我明白自己有很多问题.所以......考虑以下几点:

struct S1
{
    enum { value = 42 };
};

template <class T> struct S2
{
    typedef S1 Type;
};

template <class T> struct S3
{
    typedef S2<T> Type; 
};

template <class T> struct S4
{
    typedef typename T::Type::Type Type;  //(1)//legal?
    enum {value = T::Type::Type::value }; //(2)//legal?
};

int main()
{
    S4<S3<S2<S2<S1> > > >::value;
}
Run Code Online (Sandbox Code Playgroud)

这与MSVC9.0和Online Comeau成功编译.但是,困扰我的是我不理解typename(1)中提到的内容以及为什么我们不需要typename(2).

我已经尝试过这两种语法(合成器?),我认为它应该是MSVC上的两种失败:

    typedef typename T::typename Type::Type Type;
    enum {value = typename T::typename Type::Type::value }; 
Run Code Online (Sandbox Code Playgroud)

和 …

c++ templates dependent-name typename

10
推荐指数
1
解决办法
3272
查看次数

Why is it not required to use typename for dependent types in the following case?

I have been reading about removing reference of a type, here.

It gives the following example:

#include <iostream> // std::cout
#include <type_traits> // std::is_same

template<class T1, class T2>
void print_is_same() {
  std::cout << std::is_same<T1, T2>() << '\n';
}

int main() {
  std::cout << std::boolalpha;

  print_is_same<int, int>();
  print_is_same<int, int &>();
  print_is_same<int, int &&>();

  print_is_same<int, std::remove_reference<int>::type>(); // Why not typename std::remove_reference<int>::type ?
  print_is_same<int, std::remove_reference<int &>::type>();// Why not typename std::remove_reference<int &>::type ?
  print_is_same<int, std::remove_reference<int &&>::type>();// Why not typename std::remove_reference<int &&>::type ?
} …
Run Code Online (Sandbox Code Playgroud)

c++ templates dependent-name type-traits c++11

10
推荐指数
2
解决办法
578
查看次数

C++ - 为什么这里需要“模板”关键字?

我有以下代码:

template <typename TC>
class C
{
    struct S
    {
        template <typename TS>
        void fun() const
        {}
    };

    void f(const S& s)
    {
        s.fun<int>();
    }
};

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

当使用 gcc 9.2 和 clang (9.0) 构建它时,由于template调用fun. Clang 显示:

error: use 'template' keyword to treat 'fun' as a dependent template name
        s.fun<int>();
          ^
          template 
Run Code Online (Sandbox Code Playgroud)

我不明白为什么编译器认为fun是 上下文中的依赖名称f,因为f它本身不是模板。如果我改为C普通类而不是模板,错误就会消失;但是,我不明白为什么首先应该出现错误,因为既不S也不f依赖于TC. …

c++ templates dependent-name language-lawyer

10
推荐指数
2
解决办法
554
查看次数

为什么依赖名称可以被认为是完整的,即使实际类型直到最后才定义

考虑这个例子:

template <class T>
void Yeap(T);

int main() {
    Yeap(0);
    return 0;
}

template <class T>
void YeapImpl();

struct X;

template <class T>
void Yeap(T) {
    YeapImpl<X>(); // pass X to another template
}

template <class T>
void YeapImpl() {
    T().foo();
}

struct X {
    void foo() {}
};
Run Code Online (Sandbox Code Playgroud)

请注意,struct X直到最后才定义.我曾经相信所有使用过的名字必须在实例化时完成.但是在这里,编译器如何在定义之前将其视为完整类型?

我已经检查了cppreference中的依赖名称和函数模板实例化的绑定规则和查找规则,但是没有一个能够解释这里发生的事情.

c++ templates dependent-name c++17

9
推荐指数
1
解决办法
255
查看次数

在依赖模板名称之前使用 template 关键字

考虑到以下代码示例,我希望必须template在此处使用关键字来指导编译器将变量视为v模板。然而,MSVC 拒绝使用该template关键字,而 Clang 和 GCC 实际上需要它。在这种情况下,C++20 标准中的哪条具体规则强制或禁止使用关键字template

struct s {
    template<typename...>
    static constexpr auto v = true;
};
// all ok
static_assert([](auto x){ return decltype(x)::template v<>; }(s{}));
// clang ok, gcc ok, msvc nope
static_assert([](auto x){ return x.template v<>; }(s{}));
// clang nope, gcc nope, msvc ok
static_assert([](auto x){ return x.v<>; }(s{}));
Run Code Online (Sandbox Code Playgroud)

实例


来自 Clang 的错误消息:

<source>:10:36: error: use 'template' keyword to treat 'v'
as a dependent template name
   10 | static_assert([](auto …
Run Code Online (Sandbox Code Playgroud)

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

8
推荐指数
1
解决办法
341
查看次数

具有依赖qualified-id的类成员using声明是否应该是依赖名称?

C++ 11标准的N3337草案声明 [namespace.udecl]

using声明在声明区域中引入了一个名称,其中出现using声明.

每个using声明都是声明和成员声明,​​因此可以在类定义中使用.

在用作成员声明的using声明中,嵌套名称说明符应命名要定义的类的基类.

这通常用于在派生类的基类public中创建受保护的typedef,如下例所示,它在最新版本的Clang中成功编译:

struct A
{
protected:
    typedef int Type;
};

struct B : A
{
    using A::Type;
};

B::Type x;
Run Code Online (Sandbox Code Playgroud)

using-declaration可以引用模板类.这编译:

struct A
{
protected:
    template<typename T>
    struct Type
    {
    };
};

struct B : A
{
    using A::Type;
};

B::Type<int> x;
Run Code Online (Sandbox Code Playgroud)

也可以引用依赖基类中的模板.以下编译成功(使用typedef注释.)

template<typename T>
struct A
{
protected:
    template<typename U>
    struct Type
    {
    };
};


template<typename T>
struct B : A<T>
{
    using /* typename */ A<T>::Type; // A<T> is dependent, typename required?
    // …
Run Code Online (Sandbox Code Playgroud)

c++ templates dependent-name using-declaration language-lawyer

7
推荐指数
1
解决办法
1444
查看次数

基于参数的依赖名称查找

在cppreference.com上的描述

模板中使用的从属名称的查找被推迟到知道模板参数为止,这时ADL会检查具有外部链接的函数声明,这些声明从模板定义上下文模板实例化上下文中可见。

与此相反,以下代码片段可以使用三个编译器(MSVC,clang和gcc)很好地进行编译:

template <class T>
void CallFoo ()
{
    Foo (T ());
}


class Apple {};


int main ()
{
    CallFoo<Apple> ();
}


static void Foo (Apple)
{
}
Run Code Online (Sandbox Code Playgroud)

Foo是以下内容中的从属名称CallFoo:它取决于模板参数T。但是,Foo尽管违反了上面引用的两个规则,但是编译器仍然可以找到该函数。

  • Foo从的定义或实例中都看不到的声明CallFoo,因为它位于两者之下。
  • Foo 有内部联系。

这三个编译器都不可能有错误。我可能误会了一些东西。您能详细说明一下吗?

c++ linkage dependent-name language-lawyer argument-dependent-lookup

7
推荐指数
1
解决办法
126
查看次数