Наследование шаблонного класса с функцией-членом шаблона в C++

Вопрос: я получаю следующую ошибку для кода ниже, кто-нибудь знает почему?

Проблема: я работаю над классом (ClassB), который управляет поведением ряда классов из внешней библиотеки ( libMesh). Часть кода "... сделать что-то..." предназначена для установки некоторых переменных в этих внешних классах библиотеки, которые имеют шаблонные функции.

Я хотел бы иметь возможность установить некоторые из этих значений из конструктора наследующего класса (ClassC). Но если я сделаю это, как в коде ниже, я получу сообщение об ошибке. Если я удаляю эту команду в конструкторе, она работает просто отлично.

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

Я нашел еще один подобный пост, но я не могу применить их к моей проблеме.

Проблема доступа к внутреннему классу наследования шаблонов

Спасибо за помощь, Андрей

ОШИБКА:

XXXXXXX@XXXXX:~/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

ПРОСТОЙ КОД:

// 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
}

СПЕЦИФИЧЕСКИЙ КОД ПРОБЛЕМЫ:

//! \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"));

}

1 ответ

Решение

Компилятор не может понять, как разобрать эту вещь, потому что он не может определить, что set_value - это имя шаблона. Если вы добавите ключевое слово template после :: это решает проблему:

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

Ответ на этот вопрос очень подробно объясняет, почему: где и почему я должен поставить ключевые слова "template" и "typename"?

Другие вопросы по тегам