C++无法添加到模板内的向量中

C++ cannot add to vector inside template

本文关键字:向量 添加 C++      更新时间:2023-10-16

我正在学习模板。

我有:

template<typename SQLObject>
std::vector<SQLObject> executeSelectQueryReturnSQLVector(std::string _recordType,
                                                             std::string _sql,
                                                             int _rowCount)
{
    typename std::vector<SQLObject> v;
    if (_recordType == AppConstants::sSQLFieldObject)
    {
        for(int r=0; r < _rowCount; r++)
        {
            SQLFieldObject o;
            o.putFieldNumber(sqlite3_column_int(statement, 0));
            [snip]
            v.push_back(o);
        }
    }
    if (_recordType == AppConstants::sSQLNotificationObject)
    {
        for(int r=0; r < _rowCount; r++)
        {
            SQLNotificationObject o;
             o.putNotificationID(sqlite3_column_int(statement, 0));
             [snip]
             v.push_back(o);
        }
    }
    return v;
}

我在v.push_back(o);上得到一个编译器错误,它指出:

no matching member function for call to 'push_back'

我认为这是有道理的,为什么,对我来说很模糊,因为这是一个在编译时确定的类型名?

这是否意味着我必须实现自己的push_back()功能?

Vandevoorde和Josuttis@2003的"C++模板完整指南"仍然适用于C++11吗?

更新1:考虑此编辑:

template<typename SQLObject>
std::vector<SQLObject> executeSelectQueryReturnSQLVector(std::string _recordType,
                                                             std::string _sql,
                                                             int _rowCount)
{
    //typename std::vector<SQLObject> v;
    if (_recordType == AppConstants::sSQLFieldObject)
    {
        std::vector<SQLFieldObject> v;
        for(int r=0; r < _rowCount; r++)
        {
            SQLFieldObject o;
            o.putFieldNumber(sqlite3_column_int(statement, 0));
            [snip]
            v.push_back(o);
        }
        return v;
    }
    if (_recordType == AppConstants::sSQLNotificationObject)
    {
        std::vector<SQLNotificationObject> v;
        for(int r=0; r < _rowCount; r++)
        {
            SQLNotificationObject o;
             o.putNotificationID(sqlite3_column_int(statement, 0));
             [snip]
             v.push_back(o);
        }
        return v;
    }
    //return v;
}

我在两个return v;上都有编译器错误,比如:

no viable conversion from 'vector<class SQLFieldObject>' to 'vector<class SQLNotificationObject>'
no viable conversion from 'vector<class SQLNotificationObject>' to 'vector<class SQLFieldObject>'

我这样称呼它:

std::vector<SQLFieldObject> _v = executeSelectQueryReturnSQLVector<SQLFieldObject>    (AppConstants::sSQLFieldObject, getSQLToSelectFields(), rowCount);

std::vector<SQLNotificationObject> _v = executeSelectQueryReturnSQLVector<SQLNotificationObject>(AppConstants::sSQLNotificationObject, getSQLToSelectNotifications(), rowCount);

v的类型为std::vector<SQLObject>o的类型为SQLFieldObject。除非有一种自动的方法来投射类型为SQLFieldObjectSQLObject的对象

v.push_back(o);

这是不允许的操作。

更新

与更新代码相关的错误为:

executeSelectQueryReturnSQLVector的返回类型为std::vector<SQLObject>return语句返回std::vector<SQLFieldObject>std::vector<SQLNotificationObject>。返回的对象的类型和函数签名中的返回类型不匹配。

更优雅地处理模板:

 // A template class that returns an appropriate string based on the
 // typename used to instantiate.
 template <typename SQLObject> struct RecordTypeChooser;
 // Specialization for returning the record type for SQLFieldObjects.
 template <> struct RecordTypeChooser<SQLFieldObject>
 {
    static std::string getRecordType() { return AppConstants::sSQLFieldObject; }
 };
 // Specialization for returning the record type for SQLNotificationObjects.
 template <> struct RecordTypeChooser<SQLNotificationObject>
 {
    static std::string getRecordType() { return AppConstants::sSQLNotificationObject; }
 };
 // A template class that constructs an object and returns it.
 // The object type is based on the typename used to instantiate.
 template <typename SQLObject> struct ObjectCreator;
 // Specialization for constructing SQLFieldObjects.
 template <> struct ObjectCreator<SQLFieldObject>
 {
    static SQLFieldObject createObject()
    {
       SQLFieldObject o;
       o.putFieldNumber(sqlite3_column_int(statement, 0));
       return o;
    }
 };
 // Specialization for constructing SQLNotificationObjects.
 template <> struct ObjectCreator<SQLNotificationObject>
 {
    static SQLNotificationObject createObject()
    {
       SQLNotificationObject o;
       o.putNotificationID(sqlite3_column_int(statement, 0));
       return o;
    }
 };

 template<typename SQLObject>
 std::vector<SQLObject> executeSelectQueryReturnSQLVector(std::string _recordType,
                                                          std::string _sql,
                                                          int _rowCount)
 {
    typename std::vector<SQLObject> v;
    // Not sure whether you need this any more.
    if (_recordType == RecordTypeChooser<SQLObject>::getRecordType())
    {
       for(int r=0; r < _rowCount; r++)
       {
          v.push_back(ObjectCreator<SQLObject>::createObject());
       }
    }
    return v;
 }

更新:完全编译和链接的源

 #include <vector>
 #include <string>
 struct SQLFieldObject {};
 struct SQLNotificationObject {};
 // A template class that returns an appropriate string based on the
 // typename used to instantiate.
 template <typename SQLObject> struct RecordTypeChooser;
 // Specialization for returning the record type for SQLFieldObjects.
 template <> struct RecordTypeChooser<SQLFieldObject>
 {
    static std::string getRecordType() { return "SQLFieldObject"; }
 };
 // Specialization for returning the record type for SQLNotificationObjects.
 template <> struct RecordTypeChooser<SQLNotificationObject>
 {
    static std::string getRecordType() { return "SQLNotificationObject"; }
 };
 // A template class that constructs an object and returns it.
 // The object type is based on the typename used to instantiate.
 template <typename SQLObject> struct ObjectCreator;
 // Specialization for constructing SQLFieldObjects.
 template <> struct ObjectCreator<SQLFieldObject>
 {
    static SQLFieldObject createObject()
    {
       SQLFieldObject o;
       // o.putFieldNumber(sqlite3_column_int(statement, 0));
       return o;
    }
 };
 // Specialization for constructing SQLNotificationObjects.
 template <> struct ObjectCreator<SQLNotificationObject>
 {
    static SQLNotificationObject createObject()
    {
       SQLNotificationObject o;
       // o.putNotificationID(sqlite3_column_int(statement, 0));
       return o;
    }
 };

 template<typename SQLObject>
 std::vector<SQLObject> executeSelectQueryReturnSQLVector(std::string _recordType,
                                                          std::string _sql,
                                                          int _rowCount)
 {
    typename std::vector<SQLObject> v;
    // Not sure whether you need this any more.
    if (_recordType == RecordTypeChooser<SQLObject>::getRecordType())
    {
       for(int r=0; r < _rowCount; r++)
       {
          v.push_back(ObjectCreator<SQLObject>::createObject());
       }
    }
    return v;
 }

 void foo()
 {
    std::vector<SQLFieldObject> v1 = executeSelectQueryReturnSQLVector<SQLFieldObject>("SQLFieldObject",
                                                                                       "",
                                                                                       10);
    std::vector<SQLNotificationObject> v2 = executeSelectQueryReturnSQLVector<SQLNotificationObject>("SQLNotificationObject",
                                                                                       "",
                                                                                       10);
 }
 int main() {}

向量和实例中的类型不同。Vector只保存原始类(由于内存分配问题,无法保存子类)。但是,您可以存储指向类的指针。考虑一下:

typedef boost::shared_ptr<SQLObject> SQLObjectPtr;
typedef std::vector<SQLObjectPtr> SQLObjectPtrVector;
...
for(int r=0; r < _rowCount; r++)
{
    SQLFieldObjectPtr o(new SQLFieldObject);
    ...
    v.push_back(o);
}
#include <iostream>
#include <vector>
using namespace std;
struct A
{
    int a;
};
struct B
{
    char b;
};
template<typename T>
vector<T> fun(char type)
{
    if (type == 'A')
    {
        vector<T> v;
        // generate objects of A and append to v
        return v;
    }
    else
    {
        vector<T> v;
        // generate objects of B and append to v
        return v;
    }
}
int main()
{
    vector<A> v = fun<A>('A');
    return 0;
}