Проблемы с шаблонами в производных классах

У меня есть набор классов, которые используются для подготовки данных для сериализации. Все они являются производными от базового класса cBase, который не имеет ничего общего с вопросом.

Среди производных классов есть:

class cValue: public cBase
{
public:
cValue(){}
template< class T > void set( const T & value ){ data_ = value; }

protected:
QVariant data_;
};

Это класс для хранения простых значений, таких как строка или число. А вот класс для представления объекта (в основном то, что может содержать пары «имя-значение»):

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_;
};

Цель этого состоит в том, чтобы иметь возможность добавлять атрибуты как с уже созданными объектами: addAttribute(someName, someObject); и с необработанными значениями: addAttribute("name", 42);

Теперь этот код компилируется. Однако, если я попытаюсь создать объект, подобный этому:

cValue *tmp = new cValue();
tmp->set( 42 );
cObject obj;
obj.addAttribure("The Answer", tmp);

Я получаю следующую ошибку:

/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

Ошибка появляется в строке, где cValue«s set() функция объявлена.
Теперь, если я удалю шаблонную версию addAttribute()и поместите точно такой же код из этой функции в мой основной:

cObject obj;
cValue * tmp = new cValue();
tmp->set( 42 );
obj.addAttribure( "The Answer", tmp );

это работает отлично. Я полагаю, что это как-то связано с тем, что оба addAttribute() а также set() функции являются шаблонными, но я не понимаю, как решить эту проблему, или, по крайней мере, как обойти это.

Заметка: если возможно, я бы хотел не сделать сами классы шаблонными, только функции.

1

Решение

Проблема в том, что вы ожидаете, что компилятор вызовет addAttribure(const QString& name, cBase* value) когда используешь cValue, так как cValue происходит от cBase, Но так как они не совпадают точно, компилятор вызывает addAttribure<cValue*>(const QString& name, const cValue* value) вместо.

Вот почему (как отмечено в вашем комментарии) звонит addAttribure(name, static_cast<cBase*>(tmp)) работал.

0

Другие решения

Проблема и причина, по которой ваше исправление с помощью приведения работает, заключается в том, что компилятор выбирает функцию без шаблонов только тогда, когда вы вызываете ее именно с типами параметров ее сигнатуры. В этом случае вы не используете cBase*, но cObject*, Правда, последний может быть автоматически преобразован в первый, но компилятор видит, что он может создать экземпляр шаблона для создания функции, которая точно соответствует параметру, поэтому он выбирает это.

Вы можете пойти со своим актером:

addAttribure( name, static_cast<cBase *>(tmp) );

или вы можете использовать указатель базового класса напрямую, чтобы избежать приведения:

cBase* pBase = tmp;
addAttribure( name, pBase );
2

Возможно, есть проблема с идентификацией типа. У меня была похожая проблема с QT, но некоторое время назад. Может тебе стоит попробовать

template< class T > void set( const T & value )
{
data_ = QVariant::fromValue( value );
// or data_.setValue( value )
}
0

Это может быть как-то связано с этим:

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/keyword_template_qualifier.htm

Я смутно помню, как мои собственные шаблонные функции-члены не компилировались до того, как я явно квалифицировал их как таковые.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector