how to solve unqualified name lookup problem

202 views Asked by At

I have the following simplified program:

class Base { };

template < typename T >
class X: public T
{
    public:
        using TOP = T;
};

// with dependent template parm    
template < typename T >
class Y: public X< T >
{
    // I have to write down the full name of the base class
    using X<T>::TOP::operator =;
};

// without depending template parameter
template < typename T >
class Y: public X< Base >
{
    // I simply can use the defined type from the base class
    using TOP::operator =;
};


int main()
{
    Y< Base > y ;
}

The question is now, if there is any way to simplify the full repetition of the base class type. My original code is something like that:

template < typename VAR_TYPE >
class VarObserved: public ConstructAll2<
                   UsingHelperV_None,
                   UsingHelper_None,
                   CONTAINERL< AssignConst >,
                   CONTAINERL< Print >,
                   CONTAINERL< DataStore >,
                   CONTAINERL< Distribute_ >,
                   CONTAINERL< EndForward >,
                   CONTAINERSP< DataStoreBase, VAR_TYPE >
                   >
{
    public:
        using SELF = ConstructAll2<
            UsingHelperV_None,
            UsingHelper_None,
            CONTAINERL< AssignConst >,
            CONTAINERL< Print >,
            CONTAINERL< DataStore >,
            CONTAINERL< Distribute_ >, 
            CONTAINERL< EndForward     >,
            CONTAINERSP< DataStoreBase, VAR_TYPE >   // see text 1)
                >;

        VarObserved( const VAR_TYPE& var ): SELF{{ var }}{}
        using SELF::AssignConst::operator=;
};

As you can see, the full repetition of all the template parameters is not very "nice". Any chance to fix that?

If above code has no dependent template parameter ( change the single line 1.) ) from the example above to:

CONTAINERSP< DataStoreBase, int>

the class becomes totaly simple and much more easy to maintain:

...
VarObserved( const VAR_TYPE& var ): ConstructAll2{{ var }}{}
using AssignConst::operator=;
....

As a reference to the underlying problem I found already that question

"not declared in this scope" error with templates and inheritance

but no idea to simplify my code.

3

There are 3 answers

1
Brian Bi On BEST ANSWER

The question is now, if there is any way to simplify the full repetition of the base class type.

To find the name TOP declared in the dependent base class, you can write Y::TOP instead of X<T>::TOP, although since this may confuse readers, you should probably put a comment about why you are doing this.

The reason why this works is that it's, well, no longer unqualified lookup. Note that you don't need to write the template arguments out here (Y is the injected class name, and means the same thing as Y<T>).

3
max66 On

Maybe using a new template parameter with a default value (corrected following a Justin's observation )?

template <typename VAR_TYPE, typename CA2 = ConstructAll2<
                   UsingHelperV_None,
                   UsingHelper_None,
                   CONTAINERL< AssignConst >,
                   CONTAINERL< Print >,
                   CONTAINERL< DataStore >,
                   CONTAINERL< Distribute_ >,
                   CONTAINERL< EndForward >,
                   CONTAINERSP< DataStoreBase, VAR_TYPE >>>
class VarObserved : public CA2
 {
    public:
        using SELF = CA2;

        VarObserved( const VAR_TYPE& var ): SELF{{ var }}{}
        using SELF::AssignConst::operator=;
 };
1
Klaus On

In addition to the idea from max66 I found also the following solution, not based on specialization but on template template parameter:

template < typename VAR_TYPE >
using VarObserved_Parms = ConstructAll2<
    UsingHelperV_None,
    UsingHelper_None,
    CONTAINERL< AssignConst >,
    CONTAINERL< Print >,
    CONTAINERL< DataStore >,
    CONTAINERL< Distribute_ >,
    CONTAINERL< EndForward >,
    CONTAINERSP< DataStoreBase, VAR_TYPE >
    >;

template < typename VAR_TYPE, template <typename> class COMPONENTS >
class VarObserved2: public COMPONENTS< VAR_TYPE >
{
    using SELF = COMPONENTS< VAR_TYPE >;

    VarObserved2( const VAR_TYPE& var ): SELF{{ var }}{}
    using SELF::AssignConst::operator=;
};

After I got the idea from Brian, all implodes to nearly nothing:

template < typename VAR_TYPE >
class VarObserved: public ConstructAll2<
                   UsingHelperV_None,
                   UsingHelper_None,
                   CONTAINERL< AssignConst >,
                   CONTAINERL< Print >,
                   CONTAINERL< DataStore >,
                   CONTAINERL< Distribute_ >,
                   CONTAINERL< EndForward >,
                   CONTAINERSP< DataStoreBase, VAR_TYPE >
                   >
{
    public:
        VarObserved( const VAR_TYPE& var ): VarObserved::ConstructAll2{{ var }}{}
                                            ^^^^^^^^^^^^^ never saw that before, interesting syntax ;)
        using VarObserved::AssignConst::operator=;
};