Error incomplete type used in nested name specifier

I tried to use incomplete type in nested name specifier as the following: class A; int b= A::c; // error: incomplete type ‘A’ used in nested name specifier class A { static const int c=5; };

Introduction

There are several places in the standard that implicitly implies that your code is ill-formed, but the below quotation speaks for itself:

3.3.2p6 Point of declaration [basic.scope.pdecl]

After the point of declaration of a class member, the member name can be looked up in the scope of its class.

The problem with your code isn’t that you try to reach inside the body of an incomplete type, the problem is that you can only refer to a class member name after it has been declared.

Since your forward-declaration (of course) doesn’t introduce any member named c, it is ill-formed to refer to such name.


The misleading diagnostic…

The diagnostic issued by both gcc and clang when being fed your code is somewhat misleading, and honestly I feel a bug report is in order.

foo.cpp:3:8: error: incomplete type 'A' named in nested name specifier

We are allowed to name an incomplete type in a nested-name-specifier, but as said; we are not allowed to refer to a member that has not yet been declared.

ill-formed:

class X {
  static int a[X::x];        // ill-formed, `X::x` has not yet been declared
  static int const x = 123;
};

legal:

class X {
  int const x = 123;
  int a[X::x]; // legal, `X` is incomplete (since we are still defining it)
               //        but we can still refer to a _declared_ member of it
};

There are 2 non-template classes A, B having some static template methods.

From class A static method in B is called and from class B static method from A is called. The source code only for illustration (not real code)…

A.h

#include "B.h"
class A 
{
 public:
   template <class T>
   void f1 ()
   {
      T var1= ...;
      T var2 = B::f4(T);
   }

   template <class T>
   T f2()
   {
      return ...
   }
};

#include "A.h"
class B
{
 public:
   template <class T>
   void f3 ()
   {
      T var1= ...;
      T var2 = A::f2(T); //Error
   }

   template <class T>
   T f4()
   {
      return ...
   }
};

I am having troubles with g++ compiler in NetBeans. During the compilation the following error occurs: Error: incomplete type A used in nested name specifier, g++.

I tried to add forward declarations into both classes, but nothing was successful.

There is an older bug:

http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg01383.html

Yu Hao's user avatar

Yu Hao

118k44 gold badges232 silver badges287 bronze badges

asked Dec 31, 2010 at 21:57

Ian's user avatar

You have a circular dependency between your header files. Since your classes are so tightly intertwined, I’d suggest merging them into a single header file, structured like this:

class A
{
public:
  template <class T>
  void f1();
};

class B
{
  ...
};

template <class T>
void A::f1()
{
  // Use full definition of class B
}

If you insist on using separate header files for A and B (which won’t really make any difference since they end up including each other), you’ll need to restructure them so that one of the headers doesn’t include the other, so at least one of the dependent template functions will need to be defined in a separate file. For example:

// File "a_no_b.h"
class A
{
public:
  template <typename T>
  void f1();
};

// File "b_no_a.h"
class B
{
public:
  template <typename T>
  void f3();
};

// File "a.h"
#include "a_no_b.h"
#include "b_no_a.h"

template <typename T>
void A::f1()
{
  // Use full definition of class B
}

// File "b.h"
#include "b_no_a.h"
#include "a_no_b.h"

template <typename T>
void B::f3()
{
  // Use full definition of class A
}

answered Dec 31, 2010 at 22:17

Adam Rosenfield's user avatar

Adam RosenfieldAdam Rosenfield

385k96 gold badges510 silver badges586 bronze badges

1

Because there is a circular dependency, you need to carefully arrange the declarations of classes A and B so that they are both declared before the member functions are defined.

Here is A.h:

#ifndef A_H
#define A_H 1
class A 
{
 public:
     template <class T>
     void f1 ();

     template <class T>
     T f2();
};

#include "B.h"

template <class T>
void A::f1()
{
     T var1= ...;
     T var2 = B::f4(T);
}

template <class T>
T A::f2()
{
     return ...
}

#endif

Here is B.h:

#ifndef B_H
#define B_H 1
class B
{
 public:
     template <class T>
     void f3 ();

     template <class T>
     T f4();
};

#include "A.h"

template <class T>
void B::f3()
{
     T var1= ...;
     T var2 = A::f2(T);
}

template <class T>
T B::f4()
{
     return ...
}

#endif

With this approach, you will be able to include either A.h or B.h first and not have a problem.

answered Dec 31, 2010 at 22:18

Daniel Trebbien's user avatar

Daniel TrebbienDaniel Trebbien

37.9k17 gold badges118 silver badges192 bronze badges

1

Your problem is circular header dependency.

answered Dec 31, 2010 at 22:05

Gene Bushuyev's user avatar

1

Содержание

  1. Неполный тип в спецификаторе вложенного имени
  2. Решение
  3. Вступление
  4. Вводящая в заблуждение диагностика …
  5. CRTP — incomplete type . used in nested name specifier
  6. Frank Bergemann
  7. Advertisements
  8. Bo Persson
  9. Advertisements
  10. Frank Bergemann
  11. не собирается qt 5.15.2: error: ‘numeric_limits’ is not a class template
  12. Error used in nested name specifier

Неполный тип в спецификаторе вложенного имени

Я пытался использовать неполный тип в спецификаторе вложенного имени следующим образом:

Об этом ничего не говорится в рабочем проекте 3.4.3 / 1 N3797:

На имя класса, члена пространства имен или перечислителя можно сослаться
после того, как оператор разрешения :: объема (5.1) применяется к
спецификатор nested-name, который обозначает его класс, пространство имен или
перечисление

Так зависит ли это поведение от реализации?

Решение

Вступление

В стандарте есть несколько мест, которые неявно подразумевают, что ваш код некорректен, но приведенная ниже цитата говорит сама за себя:

3.3.2p6 Точка декларации [basic.scope.pdecl]

После точки объявления члена класса, имя члена можно искать в области видимости его класса.

Проблема с вашим кодом не в том, что вы пытаетесь найти внутри тела неполный тип, проблема в том, что вы можете ссылаться только на имя члена класса после это было объявлено.

Поскольку ваше предварительное объявление (конечно) не содержит ни одного члена с именем с, неправильно называть такое имя.

Вводящая в заблуждение диагностика …

Диагностика, выданная обоими НКУ а также лязг когда вас кормят, ваш код несколько вводит в заблуждение, и, честно говоря, я чувствую, что сообщение об ошибке в порядке.

Мы являются разрешено назвать неполный тип в вложенное имя спецификатор, но как сказал; нам не разрешено ссылаться на участника, который еще не был объявлен.

Источник

CRTP — incomplete type . used in nested name specifier

Frank Bergemann

i have a problem with applying CRTP.
Here is a short example, which demonstrate it:

char buff[TYPE::MAX — TYPE::MIN + 1];
>;

class Sample : public Base
<
public:
Sample()
: Base ()
< /* void */ >

typedef enum <
MIN = 0,
MAX = 10
> Internal_t;
>;

int main(int, char**)
<
return 0;
>

Compilation raises an error:

/TEST$ /usr/bin/g++ -o test test.cc
base.h: In instantiation of ‘Base ‘:
test.cc:5: instantiated from here
base.h:13: error: incomplete type ‘Sample’ used in nested name
specifier
base.h:13: error: incomplete type ‘Sample’ used in nested name
specifier
base.h:13: error: array bound is not an integer constant

I could do a workaround and switch to std::vector and allocate
in c’tor via some Sample::getSize().
But i wonder, if there is really no way to use the enum values in the
template base class?
(and if so: why?)

Advertisements

i have a problem with applying CRTP.
Here is a short example, which demonstrate it:

char buff[TYPE::MAX — TYPE::MIN + 1];
>;

class Sample : public Base
<
public:
Sample() : Base ()
< /* void */ >

typedef enum <
MIN = 0,
MAX = 10
> Internal_t;
>;

int main(int, char**)
<
return 0;
>

Compilation raises an error:

/TEST$ /usr/bin/g++ -o test test.cc
base.h: In instantiation of ‘Base ‘:
test.cc:5: instantiated from here
base.h:13: error: incomplete type ‘Sample’ used in nested name
specifier
base.h:13: error: incomplete type ‘Sample’ used in nested name
specifier
base.h:13: error: array bound is not an integer constant

The compiler is correct. At the line

class Sample : public Base

the Sample class is not complete, so its content isn’t known yet.

Technically you also have the problem that sizeof(Sample) depends on
sizeof(Base), which depends on Sample’s enum. That’s not going to
work!

Or pass it as a parameter to the Base constructor.

Advertisements

Frank Bergemann

The compiler is correct. At the line

class Sample : public Base

the Sample class is not complete, so its content isn’t known yet.

Technically you also have the problem that sizeof(Sample) depends on
sizeof(Base), which depends on Sample’s enum. That’s not going to
work!

Or pass it as a parameter to the Base constructor.

— thanks (once again for your help, Bo!

«in real» life i had a number of type definitions in Sample,
which i wanted to be handled in my template base class.
E.g. it should manage a container of ‘Sample’-typed elements.
Therefore i couldn’t use the Base constructor for this.
(it wasn’t just some (int) size-information).
So i shifted the necessary stuff to some extra SampleCfg class.
And made my Sample class this way:

class Sample : public Base
<
typedef SampleCfg Cfg;
[. ]
>;

But another thing i recognized for this:
If i map in some enum type:

class Sample : public Base
<
typedef SampleCfg Cfg;

typedef Cfg::MyEnum_t MyEnum_t;
[. ]
>;

Then i can’t access the MyEnum_t’s literals as Sample::FIRST_VAL (e.g.).
But i have to use Sample::Cfg::FIRST_VAL.

Why doesn’t the
typedef Cfg::MyEnum_t MyEnum_t;

. within class Sample also «adopt» the names of MyEnum_t elements into
class Sample?

Источник

не собирается qt 5.15.2: error: ‘numeric_limits’ is not a class template

Если что пишешь сам под Qt, то выкачать бы уже 6. Там такого уже не должно быть.

Можешь поподробнее описать, что ты сделал? Мне -no-pch и «-include limits» не помогло.

Печально что у Qt такое качество кода 🙁

У Qt все впорядке с кодом, проблема в неправильных заголовочниках. Если кто то сталкивался с этим отпишите пожалуйста, я бы с радостью собрал бы 6 Qt, но для встраивоемой железки нужна именно эта версия.

Гугл не предложил других вариантов, кроме того, что указал топикстартер. А создавать дубликат темы очень не хочется.

У Qt все впорядке с кодом, проблема в неправильных заголовочниках. Если кто то сталкивался с этим отпишите пожалуйста, я бы с радостью собрал бы 6 Qt, но для встраивоемой железки нужна именно эта версия.

Это и есть проблема с кодом. Что его писали неадекваты. И пользователи Qt недалеко ушли.

Но разрабы Qt использовали std::numeric_limits не подключив этот хедер. А пользователи Qt не могут пофиксить эту багу. Всё сошлось.

P.S. gcc до 11 действовал абсолютно нормально, так как по стандарту любой заголовочник стандартной библиотеки может включать любой другой заголовочник стандартной библиотеки, нельзя на это полагаться когда пишешь программу.

шестой не собирается под малинку и x86_64, гора ошибок, надоело исправлять, забил

Источник

Error used in nested name specifier

I may simply be too tired, so I’m not figuring this out. I’m working with templates for the first time. I’ve developed an algorithm to accept a function given an arbitrary number of variables (passed through an array) and numerically differentiate it an arbitrary number of times. I’m trying to template it so that it can pass and receive a few combinations of double and long double types. I’m also trying to implement the explicit instantiation as described in http://www.cplusplus.com/forum/articles/14272/ .

Line 38: Error: expected nested-name-specifier before ‘dn_dxn’
Line 38: Error: template-id ‘dn_dxn ‘ used as declarator
Line 38: Error: ‘dn_dxn(unsigned int, T (*)(U*), U*, unsigned int)’ is not a variable template
(Analogous errors for the remaining templates.)

template <> double dn_dxn( unsigned int n, double (*f)( double []), double args[], unsigned int narg);

But wouldn’t you be better just defining the entire template function in the .h file?

These are function templates; a few explicit instantiation declarations and definitions would be:

Thank you. I wasn’t putting the full function in the .h file because, as I’ve understood it from my formal programming classes, writing executed code in a header is considered bad practice.

However, I still have problems. Using the format above, I now get the error in the header «error: ‘dn_dxn’ is not a template function. In the .cpp, I’m getting «error: there is no arguments to ‘nCr’ that depend on a template parameter, so a declaration of ‘nCr’ must be available [-fpermissive]»

> I wasn’t putting the full function in the .h file because, as I’ve understood it from my formal
> programming classes, writing executed code in a header is considered bad practice.

It is ok for to define function templates in the header.

A function template by itself is not a type, or a function, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be determined so that the compiler can generate an actual function (or class, from a class template).

https://en.cppreference.com/w/cpp/language/function_template

Place the template definitions in the header, and let the templates be implicitly instantiated (unless there is a specific reason not to do so).

As an aside, avoid specialising function templates with template<>, it is almost always a bad idea.
See: http://www.gotw.ca/publications/mill17.htm

Sorry, @rcx11, I was incorrect to put the angle brackets in: @JLBorges gives the correct syntax and arrangement between .h and .cpp files.

I usually put templates in the .h file and don’t have to worry about the explicit instantiations, so I simply got it wrong in this instance.

Thank you, all. This is coming together but I’m still receiving «Line 16: error: there is no arguments to ‘nCr’ that depend on a template parameter, so a declaration of ‘nCr’ must be available [-fpermissive]». Thoughts?

Источник

I tried to use incomplete type in nested name specifier as the following:

class A;

int b= A::c; // error: incomplete type ‘A’ used in nested name specifier

class A {
    static const int c=5;
};

There is says nothing about it in the 3.4.3/1 of N3797 working draft:

The name of a class or namespace member or enumerator can be referred
to after the :: scope resolution operator (5.1) applied to a
nested-name-specifier that denotes its class, namespace, or
enumeration

So is that behavior implementation dependent?

Answer

Introduction

There are several places in the standard that implicitly implies that your code is ill-formed, but the below quotation speaks for itself:

3.3.2p6 Point of declaration [basic.scope.pdecl]

After the point of declaration of a class member, the member name can be looked up in the scope of its class.

The problem with your code isn’t that you try to reach inside the body of an incomplete type, the problem is that you can only refer to a class member name after it has been declared.

Since your forward-declaration (of course) doesn’t introduce any member named c, it is ill-formed to refer to such name.


The misleading diagnostic…

The diagnostic issued by both gcc and clang when being fed your code is somewhat misleading, and honestly I feel a bug report is in order.

foo.cpp:3:8: error: incomplete type 'A' named in nested name specifier

We are allowed to name an incomplete type in a nested-name-specifier, but as said; we are not allowed to refer to a member that has not yet been declared.

ill-formed:

class X {
  static int a[X::x];        // ill-formed, `X::x` has not yet been declared
  static int const x = 123;
};

legal:

class X {
  int const x = 123;
  int a[X::x]; // legal, `X` is incomplete (since we are still defining it)
               //        but we can still refer to a _declared_ member of it
};

Attribution
Source : Link , Question Author : Community , Answer Author : Community

Я пытался использовать неполный тип в спецификаторе вложенного имени следующим образом:

class A;

int b= A::c; // error: incomplete type ‘A’ used in nested name specifier

class A {
static const int c=5;
};

Об этом ничего не говорится в рабочем проекте 3.4.3 / 1 N3797:

На имя класса, члена пространства имен или перечислителя можно сослаться
после того, как оператор разрешения :: объема (5.1) применяется к
спецификатор nested-name, который обозначает его класс, пространство имен или
перечисление

Так зависит ли это поведение от реализации?

28

Решение

Вступление

В стандарте есть несколько мест, которые неявно подразумевают, что ваш код некорректен, но приведенная ниже цитата говорит сама за себя:

3.3.2p6 Точка декларации [basic.scope.pdecl]

После точки объявления члена класса, имя члена можно искать в области видимости его класса.

Проблема с вашим кодом не в том, что вы пытаетесь найти внутри тела неполный тип, проблема в том, что вы можете ссылаться только на имя члена класса после это было объявлено.

Поскольку ваше предварительное объявление (конечно) не содержит ни одного члена с именем с, неправильно называть такое имя.


Вводящая в заблуждение диагностика …

Диагностика, выданная обоими НКУ а также лязг когда вас кормят, ваш код несколько вводит в заблуждение, и, честно говоря, я чувствую, что сообщение об ошибке в порядке.

foo.cpp:3:8: error: incomplete type 'A' named in nested name specifier

Мы являются разрешено назвать неполный тип в вложенное имя спецификатор, но как сказал; нам не разрешено ссылаться на участника, который еще не был объявлен.

плохо сформированы:

class X {
static int a[X::x];        // ill-formed, `X::x` has not yet been declared
static int const x = 123;
};

правовая:

class X {
int const x = 123;
int a[X::x]; // legal, `X` is incomplete (since we are still defining it)
//        but we can still refer to a _declared_ member of it
};

33

Другие решения

OLLEGATOR

Linux-оид

120 / 69 / 9

Регистрация: 15.02.2011

Сообщений: 374

1

15.02.2012, 11:43. Показов 4916. Ответов 4

Метки нет (Все метки)


Подскажите пожалуйста как из class Vkladka_4 вызвать сигнал из class General?

Класс расположен выше в исходнике…

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class General;
 
class Vkladka_4:public QWidget{
 
    Q_OBJECT
 
    QPushButton *install;
    QPushButton *cancel;
    QLabel *lbl;
    QHBoxLayout *buttons;
    QVBoxLayout *message;
 
public:
 
    Vkladka_4(){
 
        install=new QPushButton("Install");
        cancel=new QPushButton("No! Aborted!");
        lbl=new QLabel("All ready! Install OS?");
 
        buttons=new QHBoxLayout();
        buttons->addWidget(cancel);
        buttons->addWidget(install);
 
        message=new QVBoxLayout(this);
        message->addWidget(lbl);
        message->addLayout(buttons);
 
        QObject::connect(cancel,SIGNAL(clicked()),SLOT(Close_All()));
 
    }
 
public slots:
 
    void Close_All(){
        emit General::Kill_Father_Now();
        // Удалить вкладку...
    }
 
};

Класс расположен ниже в исходнике…

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class General:public QWidget{                    // Основное окно...
 
    Q_OBJECT
 
    QTabWidget *t;
 
public:
 
    General(){
 
        this->resize(210,200);
 
        t=new QTabWidget(this);
        t->resize(210,200);
 
        t->addTab(new Vkladka_1(),"Step 1");
        t->addTab(new Vkladka_2(),"Step 2");
        t->addTab(new Vkladka_3(),"Step 3");
        t->addTab(new Vkladka_4(),"Final");
 
        t->setTabEnabled(1,false);
        t->setTabEnabled(2,false);
 
    }
 
public slots:
 
    void Kill_Father_Now(){
        this->close();
    }
 
};

ошибка: incomplete type ‘General’ used in nested name specifier



0



Эксперт С++

1936 / 1048 / 109

Регистрация: 29.03.2010

Сообщений: 3,167

15.02.2012, 11:58

2

Цитата
Сообщение от OLLEGATOR
Посмотреть сообщение

emit General::Kill_Father_Now();

уж простите — но Вы чушь пишите!
Создайте в классе General функциюслот с модификатором доступа public а в ней делайте emit только так! хотя я не претендую на абсолютную правильность, может каким-то танцем с бубном можно и ещё



0



OLLEGATOR

Linux-оид

120 / 69 / 9

Регистрация: 15.02.2011

Сообщений: 374

15.02.2012, 12:06

 [ТС]

3

спасибо уже совет))

Добавлено через 5 минут
а так можно!?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class General;
 
class Vkladka_4:public QWidget{
 
    Q_OBJECT
 
    QPushButton *install;
    QPushButton *cancel;
    QLabel *lbl;
    QHBoxLayout *buttons;
    QVBoxLayout *message;
 
public:
 
    Vkladka_4(){
 
        install=new QPushButton("Install");
        cancel=new QPushButton("No! Aborted!");
        lbl=new QLabel("All ready! Install OS?");
 
        buttons=new QHBoxLayout();
        buttons->addWidget(cancel);
        buttons->addWidget(install);
 
        message=new QVBoxLayout(this);
        message->addWidget(lbl);
        message->addLayout(buttons);
 
        QObject::connect(cancel,SIGNAL(clicked()),SLOT(Close_All()));
 
    }
 
public slots:
 
    void Close_All(){
         General::Kill_General_Windows();
        // Удалить вкладку...
    }
 
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class General:public QWidget{                    // Основное окно...
 
    Q_OBJECT
 
    QTabWidget *t;
 
public:
 
    General(){
 
        this->resize(210,200);
 
        t=new QTabWidget(this);
        t->resize(210,200);
 
        t->addTab(new Vkladka_1(),"Step 1");
        t->addTab(new Vkladka_2(),"Step 2");
        t->addTab(new Vkladka_3(),"Step 3");
        t->addTab(new Vkladka_4(),"Final");
 
        t->setTabEnabled(1,false);
        t->setTabEnabled(2,false);
 
    }
 
    void Kill_General_Windows(){ emit Kill_Father_Now(); }
 
public slots:
 
    void Kill_Father_Now(){
        this->close();
    }
 
};



0



Эксперт С++

1936 / 1048 / 109

Регистрация: 29.03.2010

Сообщений: 3,167

15.02.2012, 12:08

4

естественно НЕТ! т.к. Kill_General_Windows не является статической функцией!
Читайте основы С++, будет проще.



1



Linux-оид

120 / 69 / 9

Регистрация: 15.02.2011

Сообщений: 374

15.02.2012, 12:10

 [ТС]

5

спасибо



0



Forum Updated on Feb 6th

This topic has been deleted. Only users with topic management privileges can see it.

  • Hi all —

    I’m using Creator on a project. (I can’t build with it, because I don’t have a cross compiler, but it’s still the best editor and code browser I know of.) I’m getting some errors that I don’t fully understand.

    General-purpose header file:

    extern "C"
    {
        class Worker;
    }
    
    struct Tasks
    {
        EventGroupHandle_t tasksInitEventGroup
        Worker *worker;
        ...
    }
    

    Worker object:

    #include "structs.h"
    #include "worker.h"
    using namespace std;
    
    extern "C"
    {
    
    Worker::Worker()
    {
       ...
    

    I’m getting this error everywhere I reference the Worker class:

    incomplete type ‘Worker’ named in nested name specifier

    What might I be doing wrong?

    Thanks…

  • @mzimmers
    Bearing in mind that I’m not a C++ expert…

    extern "C"
    {
    Worker::Worker()
    

    how do you expect that to work in C (no classes, no ::). Come to that:

    extern "C"
    {
        class Worker;
    }
    

    what about that class in C?

    In some shape or form I think your C++ compiler is complaining when it meets Worker because it doesn’t think it has met its forward declaration class Worker;, presumably because it doesn’t work like that when it’s inside extern "C".

    Have a read through https://stackoverflow.com/questions/52261768/extern-c-with-class-and-dll to see if I’m wrong (probably am), and whether instead you fall foul of one of the rules/restrictions there?

  • In all honesty, I don’t remember why I did that. Removing them doesn’t eliminate the error, though.

    I was able to eliminate the error messages by changing my kit to one I hacked up for my target, but I’m still curious as to why this wouldn’t work if I were doing a conventional (non-cross) build.

    This would be a lot easier if I could just have a fake qmake for cross development. The docs refer to one, but no one seems to know what/where it is.

  • @mzimmers As @JonB says, class in not an ANSI C keyword. For me, your code don’t made sense. Which C++ compiler you are using?

  • I’m using the xtensa-esp32-elf-g++.exe compiler. The program builds fine (just not from Creator).

  • @mzimmers I can’t understand your code, I can’t understand how this special gcc version can compile it.
    It is not standard conform, take a look at https://isocpp.org/wiki/faq/mixing-c-and-cpp

    This could help you to made your code standard conform, and so it will compile with almost all c++ compilers… not just this special version of gcc.

  • @mzimmers said in «nested name specifier» error:

    The program builds fine (just not from Creator).

    Probably a compiler idiosyncrasy. It should slap you for that code. You can’t request C-linkage for methods, the compiler just can’t generate code for that. Use extern "C" only for the free functions you don’t want decorated (decorated here refers to symbol decoration for linkage). And don’t forget the implications of using C-linkage, e.g. there’s no overloading for undecorated symbols, meaning that the following:

    int a() {}
    int a(int) {}
    

    is a symbol redefinition error at link time.

  • OK, thanks for the education…they’re all removed and the warnings have disappeared.

  • This post is deleted!


Description


dan donovan



2005-02-14 11:44:02 UTC

gcc -v:

Reading specs from /var/gnu/3.4.0/lib/gcc/sparc-sun-solaris2.8/3.4.0/specs
Configured with: ../gcc-3.4.0/configure --prefix=/var/gnu/3.4.0 --disable-nls --
enable-languages=c,c++
Thread model: posix
gcc version 3.4.0

command line:

gcc -save-temps -I../../src/dbserver/include -I../../src/shared/include -
I../../lib/LZApplication/bin -I../../lib/LZApplicationStateValues/bin -
I../../lib/LZDBAccess/bin -I../../lib/LZDBHelper/bin -
I../../lib/LZEncryption/bin -I../../lib/LZLog2/bin -I../../lib/LZMessaging/bin -
I../../lib/LZParser/bin -I../../lib/LZStateValue/bin -
I../../lib/LZStateValueClient/bin -I../../lib/LZThread/bin -
I../../lib/LZUtility/bin -DUNIX -DOLD_GRAMMAR -I../../src -
o ../../src/dbserver/Main.o -c ../../src/dbserver/Main.C

output:

In file included from ../../src/dbserver/include/Environment.h:9,
                 from ../../src/dbserver/include/Database.h:8,
                 from ../../src/dbserver/Main.C:6:
../../src/shared/include/Collections.h: In member function `int 
ArrayCollection<T>::insert(const T&)':
../../src/shared/include/Collections.h:115: error: incomplete type 
`Environment' used in nested name specifier
../../src/shared/include/Collections.h:124: error: incomplete type 
`Environment' used in nested name specifier
../../src/shared/include/Collections.h: In member function `int 
ArrayCollection<T>::rollback(const T*, int)':
../../src/shared/include/Collections.h:190: error: incomplete type 
`Environment' used in nested name specifier
../../src/shared/include/Collections.h:199: error: incomplete type 
`Environment' used in nested name specifier
make: *** [../../src/dbserver/Main.o] Error 1

preprocessed file:

don't know how to attach this, could you tell me how?


Comment 2


Andrew Pinski



2005-02-14 15:41:34 UTC

This comes down to the following reduced testcase:
struct Logging {
  friend class Environment;
};
template<class T> struct ArrayCollection
{
  int insert(const T& theObj)
  {
    Environment::ReportError();
  }
};


This is invalid as Environment::ReportError has to be looked up at parse time and not at instainated 
time.


Comment 3


dan donovan



2005-02-14 16:11:00 UTC

I don't understand!

I have since created another dummy class which has one public static method 
that does the same as ReportError() in the Environment class. gcc doesn't 
complain about this. It is located in the same file as the insert method.

Doesn't make sense to me!

Cheers, Dan.


Comment 4


Andrew Pinski



2005-02-14 20:08:21 UTC

(In reply to comment #3)
> I don't understand!

If I reduce the source further we get:
class Environment;
template<class T> struct ArrayCollection
{
  int insert(const T& theObj)
  {
    Environment::ReportError();
  }
};
struct Environment
{
  static void ReportError(void);
};

At the point were we call Environment::ReportError, Environment is not a complete class so we don't 
know what the functions are at this point.  If we had changed the template class ArrayCollection to a 
non template, we would get the error before 3.4.0 also because it needs to be defined before.

To fix your code, maybe move a header file includes around but I did not look into where the header 
files are.


Comment 5


dan donovan



2005-02-15 09:30:37 UTC

Subject: RE:  error: incomplete type `Environment' used in nested name specifier

Thank you for putting your time into this but if you look at the
attached file, it is basically a simplified program of what is happening
in our much larger application. It compiles, links and runs as I would
expect (using gcc-3.4).

The output is:

Reporting
Obj = 15
Reporting
Reporting

I can't see why it won't work in the app!!!

Maybe I am missing something really simple...

Cheers, Dan.

Ps. I have a few more errors while trying to upgrade to 3.4. It is
pretty much all template related. I don't want to bother you as I'm sure
you've got better things to do, but if you don't ask...

Would you be willing to have a look at a list of errors I am getting?
You may have seen them before and know a quick fix! If not, no problem.

Thanks again, Dan.

-----Original Message-----
From: pinskia at gcc dot gnu dot org [mailto:gcc-bugzilla@gcc.gnu.org] 
Sent: 14 February 2005 20:08
To: Daniel Donovan
Subject: [Bug c++/19950] error: incomplete type `Environment' used in
nested name specifier



------- Additional Comments From pinskia at gcc dot gnu dot org
2005-02-14 20:08 ------- (In reply to comment #3)
> I don't understand!

If I reduce the source further we get:
class Environment;
template<class T> struct ArrayCollection
{
  int insert(const T& theObj)
  {
    Environment::ReportError();
  }
};
struct Environment
{
  static void ReportError(void);
};

At the point were we call Environment::ReportError, Environment is not a
complete class so we don't 
know what the functions are at this point.  If we had changed the
template class ArrayCollection to a 
non template, we would get the error before 3.4.0 also because it needs
to be defined before.

To fix your code, maybe move a header file includes around but I did not
look into where the header 
files are.

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19950

------- You are receiving this mail because: -------
You reported the bug, or are watching the reporter.

_____________________________________________________________________
This e-mail has been scanned for viruses by MCI's Internet Managed
Scanning Services - powered by MessageLabs. For further information
visit http://www.mci.com

_____________________________________________________________________
This e-mail has been scanned for viruses by MCI's Internet Managed Scanning Services - powered by MessageLabs. For further information visit http://www.mci.com

Понравилась статья? Поделить с друзьями:
  • Error incompatible types string cannot be converted to int
  • Error incompatible types possible lossy conversion from double to int
  • Error incompatible types possible lossy conversion from double to float
  • Error incompatible types object cannot be converted to
  • Error incompatible types nonexistentclass cannot be converted to annotation