2012-06-14 33 views
5

Pregunta: Recibo el siguiente error para el código siguiente, ¿alguien sabe por qué?Herencia de clase de plantilla con una función de miembro de plantilla en C++

Problema: estoy trabajando en una clase (ClassB) que controla el comportamiento de un número de clases de una biblioteca exterior (libMesh). La parte "... hacer algo ..." del código está diseñada para establecer algunas variables en estas clases de biblioteca externas que tienen funciones de plantilla.

Me gustaría poder establecer algunos de estos valores del constructor de la clase heredera (ClassC) .Pero si hago esto, como en el código siguiente, aparece el error. Si elimino este comando en el constructor, funciona muy bien.

También incluyo un ejemplo más detallado que utiliza produce el mismo error, pero utiliza la clase libmesh en sí misma, ilustra lo que quiero hacer un poco mejor. No estoy seguro de la utilidad de lo que estoy tratando de hacer, principalmente quiero saber por qué esto no lo hace trabajo porque parece que debería.

Encontré otra publicación similar, pero parece que no puedo aplicarla a mi problema.

Template inheritance inner class access problem

Gracias por la ayuda, Andrew

ERROR:

[email protected]:~/Documents/programs/build$ make test 
[100%] Building CXX object CMakeFiles/test.dir/source/test.cpp.o 
test.cpp: In constructor ‘ClassC<T>::ClassC()’: 
test.cpp:16:29: error: expected primary-expression before ‘int’ 
test.cpp:16:29: error: expected ‘;’ before ‘int’ 
make[3]: *** [CMakeFiles/test.dir/source/test.cpp.o] Error 1 
make[2]: *** [CMakeFiles/test.dir/all] Error 2 
make[1]: *** [CMakeFiles/test.dir/rule] Error 2 
make: *** [test] Error 2 

código simple:

// A class that sets that sets the value of something 
template <typename Type> class ClassB{ 
public: 
    ClassB(){} 
    template<typename TypeValue> void set_value(TypeValue value){ 
     // ... do something ... 
    } 
}; 

// A class that inherits ClassB 
template<typename T> class ClassC : public ClassB<T>{ 
public: 
    ClassC(){ 
     // I want to do this (if I remove this it compiles) 
     ClassB<T>::set_value<int>(1);; 
    } 
}; 

// The main function 
int main(){ 
    ClassC<double> c; 
    c.set_value<int>(1); // This works 
} 

PROBLEMA código específico:

//! \example test_libmesh.cpp 

#include <string> 
using std::string; 

// libMesh includes 
#include <libmesh.h> 
#include <libmesh_common.h> 
#include <equation_systems.h> 
#include <transient_system.h> 
#include <explicit_system.h> 
#include <parameters.h> 
#include <mesh.h> 
using namespace libMesh; 

// Fundamental behavior that will be used among many classes 
template <typename Type> class EqCore{ 
    public: 

     // Class constructor 
     EqCore(EquationSystems& sys, string name) : eq_sys(sys){ 

      // Creates a system that will store the constant(s) 
      name_.assign(name); 
      eq_sys.add_system<Type>(name_); 

      // I can set stuff from here 
      set_constant<double>("test4", 4); 
     } 

     // A function for storing a constant value 
     template<typename ParamType> void set_constant(std::string name, ParamType var){ 
      eq_sys.parameters.set<ParamType>(name) = var; 
     } 

     // A function for retrieving a constant value 
     template<typename ParamType> ParamType get_constant(std::string name){ 
      ParamType output = eq_sys.parameters.get<ParamType>(name); 
      return output; 
     } 

     // Reference to the controlling equation system 
     EquationSystems& eq_sys;  

     // The name of the system holding the constant(s) 
     string name_; 
}; 

// A test class derived 
template <typename Type> class EqBase : public EqCore<Type>{ 
    public: 

     // Constructor 
     EqBase(EquationSystems& sys, string name) : EqCore<Type>(sys, name){  

      // I want to do this! 
      // (remove this and the associated print statement in the main and it works) 
      EqCore<Type>::set_constant<double>("test5", 5); 
     } 

}; 

// Begin main function 
int main (int argc, char** argv){ 

    // Initialize libMesh and create an empty mesh 
    LibMeshInit init (argc, argv); 
    Mesh mesh; 

    // Test w/o any of the above classes 
    EquationSystems eq_sys(mesh); 
    eq_sys.parameters.set<double>("test1") = 1; 
    printf("Test 1: %f\n", eq_sys.parameters.get<double>("test1")); 

    // Test EqBase/EqCore functions set/get functions 
    EqBase<TransientExplicitSystem> eq(eq_sys, "TestSystem"); 
    eq.set_constant<double>("test2", 2); 
    printf("Test 2: %f\n", eq.get_constant<double>("test2")); 

    // Test generic creation but accessed through EqBase 
    eq.eq_sys.parameters.set<double>("test3") = 3; 
    printf("Test 3: %f\n", eq.eq_sys.parameters.get<double>("test3")); 

    // Test the constant created in EqCore constructor from EqBase 
    printf("Test 4: %f\n", eq.eq_sys.parameters.get<double>("test4")); 

    // Test the constant created in EqBase constructor from EqBase 
    printf("Test 5: %f\n", eq.eq_sys.parameters.get<double>("test5")); 

} 

Respuesta

3

El compilador no puede resolver cómo analizar esto porque no se puede determinar que set_value es el nombre de una plantilla. Si se agrega la palabra clave template después de la :: se soluciona el problema:

ClassC(){ 
    // I want to do this (if I remove this it compiles) 
    ClassB<T>::template set_value<int>(1);; 
} 

La respuesta a esta pregunta entra en gran detalle acerca de por qué: Where and why do I have to put the "template" and "typename" keywords?

+0

Gracias, tan simple. – slaughter98

Cuestiones relacionadas