2015-05-09 35 views
2

當我嘗試運行我的程序(在VS中)時出現以下生成錯誤:錯誤2676和2784(...無法推斷模板參數爲...)將結構向量插入集合時

Error 10 error C2676: binary '<' : 'const move' does not define this operator or a conversion to a type acceptable to the predefined operator 
Error 4 error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'const move' 
Error 8 error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'const move' 
Error 1 error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const move' 
Error 3 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const move' 
Error 5 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const move' 
Error 6 error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'const move' 
Error 9 error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const move' 
Error 7 error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const move' 
Error 2 error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const move' 

我不知道它們爲什麼會發生,因爲我沒有在我的move結構中定義任何運算符(見下文),也沒有任何運算符在我的代碼中導致它。

他們似乎通過此功能(這是從來沒有所謂的)原因造成的:

std::set<solution> solve(grid board, solution prev) { 
    std::set<solution> ret = {}; 
    ret.insert(prev);  
    return ret; 
} 

我的typedef /結構被上面使用:

struct move { 
public: 
    move(unsigned startX, unsigned startY, unsigned endX, unsigned endY) { 
     x0 = startX; 
     y0 = startY; 
     x1 = endX; 
     y1 = endY; 
    } 
    unsigned x0 : 4, y0 : 4, x1 : 4, y1 : 4; 
}; 

typedef std::vector<std::vector<__int8>> grid; 
typedef std::pair<__int8, __int8> point; 
typedef std::vector<move> solution; 

誰能告訴我這是爲什麼發生的,我能做些什麼來解決它?

提前致謝!

+1

您正在使用'set ',它是'set >'。 'std :: set'被排序,因此它需要'operator <'。然後'std :: vector'將它傳遞給'move'。 –

回答

1

有在Steephen的回答兩個東西,只是不適合。第一種是大多是正式的,std::set默認使用std::less,而不是operator<。儘管如此,這隻對角落很重要,因爲std::less默認使用operator<。儘管如此,還是有一個不同的問題,那就是不同的答案,因爲我無法在評論中正確地格式化代碼。

將自定義比較器作爲第二個模板參數傳遞給std::set時,必須確保它定義嚴格排序。這意味着比較器cmp必須滿足某些要求。尤其是cmp(a, a) = falsecmp(a, b) -> not cmp(b, a),其由該組(也例如std::map)使用以確定相等性。如果cmp(a, b) = falsecmp(b, a) = false(「既不小於另一個」),它將把這兩個值視爲相等。

關於你有的矢量,一個建議是使用歐幾里德距離。 (3, 0)(0, 4)之間的歐幾里得距離是5,如同(0, 3)(4, 0),(0, 0)(-5, 0)之間的歐幾里得距離和無限多的其他。這意味着不同的載體將被視爲平等,這可能不是你想要的。

作爲一個經驗法則,詞典排序是一個很好的默認設置。爲了實現這一點,你只需將操作數分成元組,以便每個元組的值都可以進行數值比較。然後,實施看起來是這樣的:

bool compare_move(move const& m1, move const& m2) 
{ 
    if (m1.x0 != m2.x0) return m1.x0 < m2.x0; 
    if (m1.y0 != m2.y0) return m1.y0 < m2.y0; 
    if (m1.x1 != m2.x1) return m1.x1 < m2.x1; 
    return m1.y1 < m2.y1; 
} 

這也有它不使用浮點運算的優勢。使用只有4位的位域這一事實可以改進一點,所以每一步只佔用16位數據。如果通過移位和OR來將這些值合併爲一個整數值,您會得到相同的結果,但我不確定該微觀優化是否值得。

1

std :: set默認情況下使用比較運算符<在內部創建二叉樹,這就是您在問題中指定了錯誤的原因。所以std :: set必須在內部爲它的所有元素保留一個訂單。因此,每次插入時,都會使用比較運算符檢查現有元素中的新元素順序,並相應地對其進行定位。

在插入到std :: set之前,您必須在struct move內部定義運算符<。我希望你能使用http://en.wikipedia.org/wiki/Euclidean_distance

bool move::operator <(struct move & rhs) 
{ 
    return ( sqrt((this->x1-this->x0)* (this->x1-this->x0) + 
        (this->y1-this->y0) * (this->y1-this->y0)) < 
      sqrt((rhs.x1-rhs.x0)* (rhs.x1-rhs.x0) + 
        (rhs.y1-rhs.y0) * (rhs.y1-rhs.y0))); 

} 

如果您希望保留自定義比較到位<進行比較,可以如下做到這一點。定義你的比較運營商customcompare`和定義的std ::設置如下:

std::set<std::vector<move>,customcompare> ret; 
+1

如果OP需要比較功能(即,他們不改變他們的設計以完全避免這個問題),那麼[taxicab](http://en.wikipedia.org/wiki/Taxicab_geometry)/ [Manhattan](http: //en.wiktionary.org/wiki/Manhattan_distance)距離可能也會起作用。 –

+0

你能爲我澄清一下嗎?我是否正確地說這個函數是必須的,因爲'set'比較了這些對象,並通過每個對象是否更大來對它們進行排序? – ricky3350

+1

@ ricky3350 std :: set正嘗試在內部使用比較運算符創建二叉樹,因此它必須在內部爲其所有元素保留一個訂單。所以每次插入時都會檢查元素之間的順序並相應地定位它。 'operator <'是std :: set的默認運算符。 – Steephen

相關問題