2

For academic purposes I'm reinventing the wheel a bit and try to write a HAL library. Now in designing it I encountered a compiler error that I do not understand.

template< class DRIVER, class PORT, class PIN >
class Instance
{
        Instance(){}
    public: 

        static void set(const bool val) 
      { 
        DRIVER::GPIOPeripheral<PORT, PIN>::set(val); 
      }
      // ...
};

The idea is that a driver class defines the 'how' and an GPIO class defines the, well, GPIO interface abstraction.

The driver class looks something like this:

class SOC_xyz 
{
    SOC_xyz(){};

public:
    template<class PORT, class PIN>
    class GPIOPeripheral
    {
        static void set(const bool val){ /* ... */ };
    }
};

The call in the actual code looks like this:

typedef Instance<SOC_t, PORT0_t, PIN0_t> GPIO0_0;
GPIO0_0::set(1);

Now the compiler gives me a

error: expected primary-expression before ',' token

for the Instance::set function where the DRIVER::GPIOPeripheral<PORT, PIN> gets called. From my understanding it tries to tell me that the class-template-member addressing part is wrong but this is beyond my C++ knowledge. Is that, what I try to do, even possible?

cigien
  • 57,834
  • 11
  • 73
  • 112
Patrick
  • 23
  • 4

1 Answers1

3
DRIVER::GPIOPeripheral<PORT, PIN>::set(val);

DRIVER is a type template parameter of the Instance class template, but the primary class template does not know anything of the dependent type GPIOPeripheral of the parameterized type DRIVER; it only knows that the latter is a type (DRIVER may not even be a class type).

As you are designing your primary class template to allow invoking a member function of a dependent class template of the parameterized type DRIVER, you need to tell this to the compiler:

DRIVER::template GPIOPeripheral<PORT, PIN>::set(val);
//      ^^^^^^^^

formally declaring that the dependent name GPIOPeripheral of the DRIVER type template parameter of the Instance class template is a template.

The template disambiguator for dependent names

Similarly, in a template definition, a dependent name that is not a member of the current instantiation is not considered to be a template name unless the disambiguation keyword template is used or unless it was already established as a template name: [...]


Also, note that as you are declaring the GPIOPeripheral class template using the class, with default access modifier private, meaning the set member function is private and cannot be accessed from outside the (lexical) scope of the class template itself of a friend to it.

dfrib
  • 70,367
  • 12
  • 127
  • 192
  • 1
    The `template` keyword did the trick. Thank you very much. It makes sense that the nature of the object/function to be called is specified. I assumed the compiler would deduct that from the actual call in the program. As for the `private` issue: That is a artifact of me leaving out unhelpful code. The real code has the public statement in there. – Patrick Jan 10 '21 at 12:03