Question

I have a class template with three constructors and one of them is function template.

template<class T>
class TemplateOverLoading
{
public:
    TemplateOverLoading(void){};
    ~TemplateOverLoading(void){};
    //constructor that take reference
    TemplateOverLoading(std::string& qName, T& qValue )
        :   mName(qName),
            mValue( &qValue)
    {
        std::cout << "Reference -> "<< *mValue <<"\n";
    }

    //Template constructor that takes array
    template<class T, int N>
    TemplateOverLoading(std::string& qName, T (&t)[N])
        :   mName(qName),
            mValue(t)
    {
        std::cout << "Array ->\n";
        for(int i = 0; i < N; i++)
            std::cout<< mValue[i];
        std::cout << std::endl;
    }

    //Other constructor that take pointer
    TemplateOverLoading(std::string& qName, T* qValue )
        :   mName(qName),
            mValue( qValue)
    {
        std::cout << "Pointer "<< *mValue <<"\n";
    }
private:
    T*               mValue;
    //T*              mValueArray;
    std::string&    mName;
};

From my application I need to distinguish between reference type/value, pointer and array and perform specific operation. Hence I decided to have to different constructors.

I am trying to invoke the constructor in the following manner:

int init(10);
int intArray[10] = {0,1,2,3,4,5,6,7,8,9};
TemplateOverLoading<int> mInt(std::string("mInt"), init);    
TemplateOverLoading<int> mIntArray( std::string("mIntArray"), intArray );

The problem is if the constructor with the pointer is defined the array constructor is never invoked. However, if I comment that one out it prints the array as it should.

Output:

(when pointer constructor is present)
Reference -> 10
Pointer 0

(when pointer constructor is not present)
Reference -> 10
Array ->
0123456789

So syntactically it is possible and it is correct deducing the the array size N.

Obviously I am confusing the compiler when the array constructor is present. So instead of letting the compiler automatically deduce I tried to specify the template parameter for the array constructor to only find out unlike the regular function, template parameters cannot be specifically specified.

I thought of introducing a dummy parameter in the array constructor to differentiate the overloading but it doesn't seem nice.

Is there any other way to resolve this? Any clue appreciated.

Was it helpful?

Solution

Make your pointer constructor parameter to T*& qValue.

TemplateOverLoading(std::string& qName, T*& qValue )
    :   mName(qName),
        mValue( qValue)
{
    std::cout << "Pointer "<< *mValue <<"\n";
}

By making it a reference to a pointer, array-to-pointer decay is prevented and the array constructor is chosen.

Also, I don't see how your code compiles, I see many errors:

Your template constructor has a parameter class T, this conflicts with the class T of the class template:

template<class T, int N>
    TemplateOverLoading(std::string& qName, T (&t)[N])

This needs to be changed to something else than class T, for example class U:

template<class U, int N>
        TemplateOverLoading(std::string& qName, U (&t)[N])

Your constructors also take a non-const lvalue reference, non const reference cannot bind to temporaries, which you are passing in the constructor call, i.e. std::string("mIntArray"). You need to change it to const std::string& or take it by value. Also your member std::string& mName; is a reference, you should remove the & there.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top