I have a set of classes that are used to prepare data for serialization. All of them are derived from the base class cBase, which doesn’t hold anything related to the question.
Among the derived classes there are:
class cValue: public cBase
{
public:
cValue(){}
template< class T > void set( const T & value ){ data_ = value; }
protected:
QVariant data_;
};
This is the class for holding simple values like a string or a number. And here is a class to represent an object (basically something that can hold “name-value” pairs:
class cObject: public cBase
{
public:
cObject(){}
void addAttribure( const QString & name, cBase * value )
{
if( attributes_.contains( name ) )
delete attributes_[name];
attributes_[name] = value;
}
template< class T > void addAttribure( const QString & name, const T & value )
{
cValue * tmp = new cValue();
tmp->set( value );
addAttribure( name, tmp );
}
protected:
QMap< QString, cBase * > attributes_;
};
The purpose of this is to be able to add attributes both with already-created objects: addAttribute(someName, someObject); and with raw values: addAttribute("name", 42);
Now, as it is, this code compiles. However, if I try to create an object like this:
cValue *tmp = new cValue();
tmp->set( 42 );
cObject obj;
obj.addAttribure("The Answer", tmp);
I’m getting the following error:
/usr/include/qt4/QtCore/qvariant.h:429:12: error: 'QVariant::QVariant(void*)' is private
../../source/private/../include/MyClasses.h:36:51: error: within this context
The error appears on the line where cValue‘s set() function is declared.
Now if I remove the templated version of addAttribute(), and place the exact same code from that function into my main:
cObject obj;
cValue * tmp = new cValue();
tmp->set( 42 );
obj.addAttribure( "The Answer", tmp );
it works fine. I figure it has something to do with the fact that both addAttribute() and set() functions are templated, but I fail to understand how to fix this issue, or at least how to make a workaround.
Note: if possible, I would like to not make the classes themselves templated, only the functions.
The problem is that you’re expecting the compiler to call
addAttribure(const QString& name, cBase* value)when usingcValue, becausecValueis derived fromcBase. But as they are not an exact match, the compiler callsaddAttribure<cValue*>(const QString& name, const cValue* value)instead.That’s why (as noted in your comment) calling
addAttribure(name, static_cast<cBase*>(tmp))worked.