【问题标题】:Copying templated vector复制模板矢量
【发布时间】:2011-07-16 01:04:12
【问题描述】:

我目前有一个使用我的模板作为其类型的向量:

vector<hashData> myTable;

hashData 是一个类:

class hashData{
    public:
        // constructor for hashData
        hashData(hashType data){
            this->data = data;
            this->isActive = true;
            this->deleted = false;
        }

        hashData(){
            this->isActive = false;
            this->deleted = false;
        }

        // internal data for hashTable
        hashType data;
        bool deleted;
        bool isActive;
    };

当我尝试执行如下操作时:

vector<hashData> oldTable = myTable;

我收到此错误消息:

错误 C2440:“正在初始化”:不能 从 'std::vector<_ty>' 转换为 'std::vector<_ty>'

hashtable.h(211):错误 C2440: “正在初始化”:无法从 'std::vector<_ty>' 到> 'std::vector<_ty>' 与 [_Ty=hashTable::hashData] 和 [_Ty=unsigned long]

没有构造函数可以采用源类型,或者构造函数重载决议不明确

关于为什么会发生这种情况的任何想法?我的参考资料似乎认为这是可能的,所以我不确定我的错误在哪里。

编辑:这是 hashTable 实现的完整头文件。对于代码的长度,我深表歉意,但我想包含所有内容,因为我最初的“片段”似乎不够。

// 驱动文件 #include "hashTable.h"

int main(void){
    // hash table creation
    hashTable<unsigned long> newTable(3);

    // hash table insertion
    newTable.addRecord(5);
    newTable.addRecord(6);
    newTable.addRecord(7);
    newTable.addRecord(8);
}    

// 哈希表头文件

// BEGIN HEADER FILE
#ifndef HASHTABLE_H
#define HASHTABLE_H

// Includes (system libraries)
#include <iostream>
#include <vector>

// Includes (custom libraries)

// Namespace
using namespace std;

// hashTable class
template <typename hashType>
class hashTable{
public:
    // constructor
    hashTable(int tableSize, string collisionMode = "Linear"){
        this->myTable.resize(optimizeTableSize(tableSize));
        this->collisionMode = collisionMode;
        this->activeRecords = 0;
    }

    // hashTable operations
    void addRecord(hashType);
    void deleteRecord(hashType);
    pair<bool,int> locateRecordPosition(hashType);
    bool searchRecord(hashType);
    hashType returnRecord(hashType);

    // hashTable mainteance
    void considerRehash();
    void rehashTable();
    int optimizeTableSize(int);

    // hashTable math
    bool isPrime(int);
    int nextPrime(int);

    // collision monitoring
    void collisionLogUpdate(int, string);
    int collisionLogAverage();

    // hash table internal class
    class hashData{
    public:
        // constructor for hashData
        hashData(hashType data){
            this->data = data;
            this->isActive = true;
            this->deleted = false;
        }

        hashData(){
            this->isActive = false;
            this->deleted = false;
        }

        // internal data for hashTable
        hashType data;
        bool deleted;
        bool isActive;
    };

private:
    // hashing function
    int calculateHash(hashType, int);

    // hashTable data structure
    vector<hashData> myTable;
    int activeRecords;

    // collision information
    deque<pair<int, string> > collisionLog;
    string collisionMode;
};

// hashTable implementation
// insert a record into the hash table
template <typename hashType>
void hashTable<hashType>::addRecord(hashType toAdd){
    // search for the record
    pair <bool, int> recordPos = locateRecordPosition(toAdd);

    // analyze the results
    if (recordPos.first == true) // the record already exists and is active
        return;
    // otherwise, go ahead and insert the record at this location
    myTable[recordPos.second] = hashData(toAdd);

    // update our count of active records
    activeRecords++;

    // consider a rehash of the hashTable
    considerRehash();
}

// delete a record from the hash table
template <typename hashType>
void hashTable<hashType>::deleteRecord(hashType toDelete){
    // search for the record
    pair <bool, int> recordPos = locateRecordPosition(toDelete);

    // analyze the results
    if (recordPos.first == false) // the record does not exist -- there is nothing to delete here!
        return;

    // otherwise, go ahead and perform a shallow deletion at this area
    myTable[recordPos.second].deleted = true;

    // update our count of active records
    activeRecords--;

    // consider a rehash of the hashTable
    considerRehash();
}

// find position of record within hash table (if such position exists)
template <typename hashType>
pair<bool,int> hashTable<hashType>::locateRecordPosition(hashType toFind){
    // setup data structures
    int collisionNum = 0;
    unsigned int currentPos;

    // search for the entry within the table
    currentPos = calculateHash(toFind, myTable.size());

    // enter a while loop for checking if we've found the item
    while(myTable.at(currentPos).isActive && !myTable.at(currentPos).deleted){
        // check to see if the entry found at the expected position matches
        if(myTable.at(currentPos).data == toFind){
            // update the collisionLog
            collisionLogUpdate(collisionNum,"locateRecord");

            // return the position of the item
            return pair<bool, int>(true,currentPos); // we've successfully found the item
        }

        // otherwise, we need to look for the correct location
        if (collisionMode == "Quadratic"){
            currentPos += 2 * ++collisionNum - 1;
            if(currentPos >= myTable.size())
                currentPos -= myTable.size();
        }
        else if (collisionMode == "Linear"){
            currentPos += 2 * ++collisionNum - 1;
            if(currentPos >= myTable.size())
                currentPos -= myTable.size();
        }

        // reloop and search again
    }

    // update the collisionLog
    collisionLogUpdate(collisionNum,"locateRecord");

    // if we escaped the loop, we were unable to find the item in the table -- return the first open location
    return pair<bool, int>(false,currentPos); // we didn't find the item
}

// return whether a record exists within hash table
template <typename hashType>
bool hashTable<hashType>::searchRecord(hashType toFind){
    return locateRecordPosition(toFind).first; // we didn't find the item
}

// return the contents of a record from the hash table
template <typename hashType>
hashType hashTable<hashType>::returnRecord(hashType toReturn){
    if (locateRecordPosition(toReturn).first) // if the record actually exists
        return myTable[locateRecordPosition(toReturn).second].data;
    else
        return hashType();
}

// calculate hash value
template <typename hashType>
int hashTable<hashType>::calculateHash(hashType toHash, int tableSize){
    if (toHash < 0) // if we have a negative number, change it prior to hashing
        toHash = (toHash*-1);
    return ((toHash*37) % tableSize);
}

// review the collision log and consider rehashing
template <typename hashType>
void hashTable<hashType>::considerRehash(){
    // check if we have used up more then half of the table, if we have, rehash
    if((activeRecords + 1) > ((signed) myTable.size() / 2))
        rehashTable();

    // check the current average of collisions
    // if the average number of collisions is greater then 20% of the table size (meaning it had to search through 20% of table), rehash
    else if((collisionLogAverage() > (myTable.size() * .20)) && (myTable.size() >= 100))
        rehashTable();

    // check the last operations number of collisions
    // if the number of collisions encounter is greater then 30% of the table size (meaning it had to search through 30% of table), rehash
    else if((collisionLog.back().first > (myTable.size() * .30)) && (myTable.size() >= 100))
        rehashTable();
}

// rehash the table
template <typename hashType>
void hashTable<hashType>::rehashTable(){
    // make a copy of the existing vector
    vector<hashType> oldTable = myTable;

    // reallocate myTable
    myTable.resize(optimizeTableSize(myTable.size() * 2)); // double the size of the current table

    // clear myTable
    myTable.clear();

    // copy the existing table over
    for (unsigned int i = 0; i < oldTable.size(); i++){
        if(oldTable[i].isActive && !oldTable[i].deleted){
            addRecord(oldTable[i].data);
        }
    }
}

// optimze table size
template <typename hashType>
int hashTable<hashType>::optimizeTableSize(int tableSize){
    // if we are performing quadratic probing, we need to optimize the table size to be a prime number, to prevent loops
    if (!isPrime(tableSize)){
        return nextPrime(tableSize);
    }

    // we only need to bother with optimizing the table size IF we are performing quadratic probing
    else
        return tableSize;
}

// determine if prime number
template <typename hashType>
bool hashTable<hashType>::isPrime(int numberToEvaluate){
    if(numberToEvaluate == 0)
        return true;

    numberToEvaluate = abs(numberToEvaluate);

    if(numberToEvaluate % 2 == 0) return true;

    for(int i = 3; i <= sqrt((float)numberToEvaluate); i+=2)
        if(numberToEvaluate % i == 0)
            return false;

    return true;
}

// find the next prime number
template <typename hashType>
int hashTable<hashType>::nextPrime(int numberToEvaluate){
    if (numberToEvaluate % 2 == 0)
        numberToEvaluate++;

    for (; !isPrime(numberToEvaluate); numberToEvaluate+=2)
        ;

    return numberToEvaluate;
}

// update collision log with a new entry
template <typename hashType>
void hashTable<hashType>::collisionLogUpdate(int numberOfCollisions, string operationPerformed){
    // add an entry to the log
    collisionLog.push_back(pair<int,string>(numberOfCollisions, operationPerformed));

    // verify we don't have more then 5 entires, if so, remove them
    while(collisionLog.size() > 5)
        collisionLog.pop_front();
}   

template <typename hashType>
int hashTable<hashType>::collisionLogAverage(){
    // add the last five entries, then take their average
    // the log should be maxed at five entries.. so just add them all

    // average holder
    int average;

    // loop through log
    for (unsigned int i = 0; i < collisionLog.size(); i++){
        average = collisionLog.at(i).first;
    }

    // average the sum
    average = average/5;

    // return the calculated average
    return average;
}   

// END HEADER FILE
#endif

【问题讨论】:

  • 错误信息中剩下的几行是什么?为简洁起见,“错误列表”窗口仅显示每个错误的第一行。查看“输出”窗口以查看完整的编译错误;它应该告诉你这两种_Ty 类型是什么。很有可能,myTableoldTable 实际上属于不同的类型。
  • 您在构造函数参数中是否缺少引用?
  • (请不要在所有内容之前使用this-&gt;,这只是噪音。无论如何,更喜欢初始化列表。)
  • @GMan——我通常不喜欢初始化列表——可读性(从我的角度来看)随着它们的使用而降低。我知道我不需要使用它-> -- 我只是在快速开发某些东西时使用它,以便 Intellisense 快速向我显示可用的成员名称。
  • @James McNellis -- 抱歉,我最初应该这样做。我已经发布了完整的消息。我现在正在生成一个代码片段。

标签: c++ templates vector copy-constructor


【解决方案1】:

myTable 不是 std::vector&lt;hashData&gt; - 仔细检查。

编辑:源发布后。

vector<hashData> myTable;
vector<hashType> oldTable = myTable;

hashData != hashType

【讨论】:

  • 不幸的是,它是。直接从头文件“vector myTable;”复制而来
  • @BSchlinker:宏、命名空间和 typedef 可以使 hashData 在不同的地方有不同的含义。按照 James McNellis 在评论中的建议,找出所涉及的类型到底是什么。
  • @Erik -- 我继续发布了头文件的代码和它的驱动程序。
  • @Erik -- 很好。我需要想出更好的命名结构来防止这种情况在未来发生。感谢您的帮助。
【解决方案2】:

hashtable.h(211):错误 C2440: “正在初始化”:无法从 'std::vector<_ty>' 到> 'std::vector<_ty>' 与 [_Ty=hashTable::hashData] 和 [_Ty=unsigned long]

看看你的样子

std::vector<hashData> oldTable = myTable; 

其中 myTablestd::vector&lt;unsigned long&gt;不是 std::vector&lt;hashData&gt;

【讨论】:

  • 我认为这个错误信息可能具有欺骗性,因为 hashData 被周围类的初始化设置为 unsigned int。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
相关资源
最近更新 更多