Home > Software engineering >  Problem with operator of templated inherited class
Problem with operator of templated inherited class

Time:01-18

I am trying to figure a problem with a piece of code that I wrote.

I have two structs (bar and foo) that can be used to contruct a templated class myClass. For this example, the structs will contain information about the size of a vector of a templated quantity (called baseType).

There is also a third struct called infoClass which will contain some information about the object, e.g., its name.

The class myClass will inherite from infoClass and from either bar or foo.

When I write the operator for myClass, the compiler is allowing me to do: myClass<double, foo> = myClass<double, bar> myClass<double, bar>;

I was able to track the problem to the constructor myClass (const infoClass& obj).

If I put an extra parameter I will get the error I am expecting saying: error: conversion from ‘myClass<[...],bar>’ to non-scalar type ‘myClass<[...],foo>’ requested

However, I am not understanding why do I need to put an extra parameter in the constructor for the code to work as expected.

Can anyone shed some light on this?

I have the following code:

#include <iostream>
#include <vector>

struct bar
{
    int size{10};
};

struct foo
{
    int size{15};
};

struct infoClass
{
    std::string name;
};

template<typename baseType, typename myType>
class myClass;


typedef myClass<double, bar> doubleBar;
typedef myClass<double, foo> doubleFoo;

template<typename baseType, typename myType>
class myClass
:
public infoClass,
public myType
{
    private:
    std::vector<baseType> data_;

    public:
        myClass(double initValue) : data_(this->size,{initValue}){}

        myClass (const infoClass& obj) // myClass (const infoClass& obj, double someVar) //this works
        : 
        data_(this->size,{0})
        {
            this->name = obj.name;
        }

        std::vector<baseType>& data() {return data_;}
        const std::vector<baseType>& data() const {return data_;}
};


template<typename baseType, typename myType>
myClass<baseType, myType> operator (const myClass<baseType, myType>& obj1, const myClass<baseType, myType>& obj2)
{
    if(obj1.data().size() != obj2.data().size())
        std::cout << "error, sizes are different" << std::endl;
    
    myClass<baseType, myType> result(0);

    for(int i=0; i < obj1.data().size(); i  )
    {
        result.data()[i] = obj1.data()[i]   obj2.data()[i];
    }

    return result;
}

int main() 
{

    doubleBar a(3);
    doubleBar b(4);

    doubleBar c = a   b;

    doubleFoo e = a   a;

    std::cout << "End" << std::endl;    

    return 0;
}

CodePudding user response:

You problem is indeed in myClass (const infoClass& obj) constructor. Such constructor is called "converting construcor" and can be used by compiler to implicitly convert one type to another.

Since both of you types doubleBar and doubleFoo can be implicitly converted to infoClass comlpiler then can convert it back to either of these classes. To prevent this implicit behavior just add keyword explicit in this constructor declaration, i.e.:

explicit myClass (const infoClass& obj)

This will tell compiler not to use this constructor for implicit conversion and everything will work as you expect.

  •  Tags:  
  • c
  • Related