B has not been declared



  • Hallo,

    folgendes Minimalbeispiel welches mein Problem reflektiert. Ich gebe alle Dateien an und verstehe nicht warum der compiler mit der Meldung "B has not been declared" schreibt obwohl ich die Klasse B verfügbar mache. Wichtig: Impl.h ist keine Klasse sondern bietet nur die deklaration/definition von bar() an:

    main.cpp

    #include <iostream>
    #include "A.h"
    
    int main(int argc, int** argv)
    {
        int b = 8;
    
        A<double> a = A<double>(b);
    
    }
    

    A.h

    #include "Impl.h"
    
    #ifdef INCLUDE_A
    #define INCLUDE_A
    
    template <class T> class A
    {
        public:
         A<T>(int b)
         {
            bar<T>(b);
         };
         ~A<T>() { };
    
    };
    #endif
    

    Impl.h

    #include "B.h"
    
    template<class T> inline void
    bar(int b, B b)
    {
    //    std::cout << b << std::endl;
    }
    

    B.h

    #ifdef INCLUDE_B
    #define INCLUDE_B
    
    template <class T> class B
    {
        public:
            B() { };
            ~B() { };
    
    };
    
    #endif
    


  • Wie wärs mit

    #ifndef INCLUDE_A
    //und
    #ifndef INCLUDE_B 
    //anstatt
    #ifdef INCLUDE_A
    //und
    #ifdef INCLUDE_B
    

    😕



  • eh...das ändert leider nix



  • #include "B.h"
    
    template<class T> inline void
    bar(int b, B b) //2 x ein Formalparameter b, und B ist ein Template...
    
    {
    //    std::cout << b << std::endl;
    }
    

  • Mod

    Mehrere kleine Fehler, ich fange mal hinten an:
    B.h

    #ifdef INCLUDE_B
    #define INCLUDE_B
    
    template <class T> class B
    {
        public:
            B() { };
            ~B() { };
    
    };
    
    #endif
    

    Soweit ok.

    Impl.h

    #include "B.h"
    
    template<class T> inline void
    bar(int b, B b)   // Hier verwendest du 2x den Bezeichner b, was nicht erlaubt ist. Außerdem bezeichnet B alleine keinen Typ, du musst das template spezialisieren, also sowas wie B<T>. 
    {
    //    std::cout << b << std::endl;
    }   // hier fehlt ein ;
    

    A.h

    #include "Impl.h"
    
    #ifdef INCLUDE_A
    #define INCLUDE_A
    
    template <class T> class A
    {
        public:
         A<T>(int b)  // das <T> ist unnötig
         {
            bar<T>(b);  // Der Konstruktor von bar ist oben anders deklariert. Er nimmt genau zwei Argumente.
         };
         ~A<T>() { }; // hier ist das <T> ebenfalls unnötig
    
    };
    #endif
    

    main.cpp

    #include <iostream>
    #include "A.h"
    
    int main(int argc, int** argv)
    {
        int b = 8;
    
        A<double> a = A<double>(b);
    
    }
    

    Wenn du die Änderungen umsetzt, geht's.



  • eh doch sorry...



  • ich danke euch für eure Hilfe. Leider funktioniert es bei meinem normalen code nicht obwohl es hier im minimalbeispiel funktioniert. Kann es sein dass die Kompilierreihenfolge eine Rolle spielt? Könnte es dass wenn B.h erst irgendwie nach Impl.h kompiliert wird bzw. nach A.h dass es dann nicht geht?



  • SeppJ schrieb:

    Mehrere kleine Fehler, ich fange mal hinten an:

    #include "B.h"
    
    template<class T> inline void
    bar(int b, B b)   // ...
    {
    //    std::cout << b << std::endl;
    }   // hier fehlt ein ; MIT SICHERHEIT NICHT!
    

    Das Semikolon ist nicht nach dem "}" nötig (Das gilt auch für die Methoden im Header, die eine Implementierung direkt enthalten (Bei der reinen Methoden/Funktionsdeklaration ist es nötig).

    Zudem sehe ich sehr viele Fehler in dem Originalcode, werde zeitlich aber nicht darauf eingehen.



  • Ok - nochmal von vorn. Ich hoffe jetzt das Minimalbeispiel so zu haben wie bei meinem großen code:

    1. Die main.cpp liegt im obersten Ordner
    #include <iostream>
    #include "A.h"
    
    int main(int argc, int** argv)
    {
        int b = 8;
    
        A<double> a = A<double>(b);
    
    }
    

    Impl.h liegt im Unterordner variante/Impl.h. Also da wo z.B. main.cpp liegt
    ist noch ein Ordner variante in dem jetzt Impl.h liegt:

    #include "../B.h"
    
    inline void
    bar(int b)
    {
    //    std::cout << b << std::endl;
        }
    

    Dann die A.h die wieder neben der main.cpp liegt.

    #include "Impl_Env.h"
    #include "B.h"
    
    #ifndef INCLUDE_A
    #define INCLUDE_A
    
    template <class T> class A
    {
        public:
                A<T>(int b);
               ~A<T>() { };
    
    };
    
    #include "A.imp"
    
    #endif
    

    Und die A.imp die ebenfalls neben der A.h liegt:

    template<class T> 
    A<T>::A(int b)
    { 
        bar(b);
    };
    

    Und die B.h die neben der A.h liegt:

    #ifndef INCLUDE_B
    #define INCLUDE_B
    
    template <class T> class B
    {
        public:
        	B() { };
    	~B() { };
    
    };
    
    #endif
    

    Und schießlich die Impl_Env.h die ebenfalls neben der main.cpp liegt. Sie ist dafür verantwortlich dass auch variante/Impl.h eingebunden wird. Natürlich ist hier nur ein Zweig vorhanden - also immer mit -DFLAG kompilieren.

    #ifdef FLAG
    #include "variante/Impl.h"
    #endif
    

    Ich bekomme folgende Fehlermeldung von meinem gcc compiler:

    A.imp:4: error: there are no arguments to ‘bar’ that depend on a template parameter, so a declaration of ‘bar’ must be available
    

    Das ist mir nicht klar weil bar eigentlich vorhanden ist.


Anmelden zum Antworten