2

I got a traits class, AttributeTraits, that uses a smart-pointer template class, MySmartPointer :

template<typename T>
class MySmartPointer {};

template<template <typename> class SP = MySmartPointer>
struct AttributeTraits {
    template <typename T>
    using SmartPointerClass = SP<T>;
};

AttributeTraits use alias to hold the template class it have. Now, I need that Attribute class that gets a trait class will use a typedef/alias to the smart pointer class, such:

template <typename Traits>
struct Attribute {
    typedef typename Traits::SmartPointerClass<int> SmartPointerType; // error: non-template 'SmartPointerClass' used as template
    using SmartPointerType2 = typename Traits::SmartPointerClass<int>; // error: expected ';' before '<' token
    using SmartPointerType3 = Traits::SmartPointerClass<int>; // error: non-template 'SmartPointerClass' used as template
};

But none of the 3 options above works...

o.z
  • 1,086
  • 14
  • 22

1 Answers1

6

This is one of those times where your dependent class is a template, so you have to use the awkward template syntax when defining your alias:

template <typename Traits>
struct Attribute {
    typedef typename Traits::template SmartPointerClass<int> SmartPointerType;
    using SmartPointerType2 = typename Traits::template SmartPointerClass<int>; 
    using SmartPointerType3 = typename Traits::template SmartPointerClass<int>; 
};

See this documentation for description of when you need the template keyword:

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

This StackOverflow Answer also provides some good background.

Community
  • 1
  • 1
AndyG
  • 39,700
  • 8
  • 109
  • 143