2012-07-21 73 views
1

我想重载模板类的[]运算符与模板参数有关。像这样:C++ template class overload []运算符

template< 
    typename T, 
    template<typename> class Property, 
    template<typename> class Key1, 
    template<typename> class Key2> 
class a_map 
{ 
public: 
    const Property<T>& operator[](const Key1<T>& k) const 
    { return _values[k.index()]; } 
    const Property<T>& operator[](const Key2<T>& k) const 
    { return _values[k.index()]; } 
protected: 
    std::vector<Property<T> > _values; 
}; 

我会使用这个类,像这样:

int main() 
{ 
    a_map<float, prop, key_a, key_b> pm; 
} 

基本上我希望能够访问_values矢量内的元素,而不必担心到很多有关Key类型。重要的是他们有一个index()成员。

不过,我得到以下错误

error C2535: 'const Property &a_map::operator [](const Key1 &) const' : member function already defined or declared

即使key_akey_b是两个完全以不同 类型 类模板。

我错过了什么吗?编译器是否担心在某些情况下Key1<T>Key2<T>实际上可能是同一类型?

编辑 这些都是main

template<typename T> 
struct prop 
{ 
    T weight; 
    T height; 
}; 


template<typename T> 
class key_a 
{ 
public: 
    int index() { return _i; } 
private: 
    int _i; 
}; 

template<typename T> 
class key_b 
{ 
public: 
    int index() { return 3; } // Always return 3 

使用编辑 我使用MVC++ 2008编译器编译的类模板。

+2

您是否100%确信'Key1'和'Key2'是不同的模板?尝试'std :: vector'和'std :: list'作为测试,或者类似的东西。 – 2012-07-21 21:07:43

+2

'key_a'和'key_b' - 类型?根据你的声明'key_a'和'key_b'必须是类*模板*,而不是类型。您将第二,第三和第四个模板参数声明为* template-template *参数。所以,你必须指定*模板*作为参数。如果'key_a'和'key_b'只是* types *,那么你的代码甚至不应该编译。在你的测试中给出一个具体的例子,说明什么是'key_a'和'key_b',给你这个错误。 – AnT 2012-07-21 21:09:57

+0

这是编译器错误还是链接器错误? – 2012-07-21 21:14:19

回答

0

像这样编译好......记下如何定义Prop/K1/K2。

#include <vector> 

template< 
    typename T, 
    template<typename> class Property, 
    template<typename> class Key1, 
    template<typename> class Key2> 
class a_map 
{ 
public: 
    const Property<T>& operator[](const Key1<T>& k) const 
    { return _values[k.index()]; } 
    const Property<T>& operator[](const Key2<T>& k) const 
    { return _values[k.index()]; } 
protected: 
    std::vector<Property<T> > _values; 
}; 

template <typename T> struct K1 { int index() const { return 0; } }; 
template <typename T> struct K2 { int index() const { return 0; } }; 
template <typename T> struct Prop { }; 

int main() 
{ 
    a_map<float, Prop, K1, K2> m; 
} 
+0

请记住,编译器甚至不会查看未使用的模板函数。你的主函数不使用'operator []',所以这两个例程不被检查。加这个'K1 k1; m [k1];'你将会得到'错误:在'm [k1]'中没有匹配'operator []'' – Adam 2012-07-21 21:19:09

+0

@Adam:当然,没有匹配:在Tony的例子中,'a_map'被实例化为' T =浮动'。你为什么试图使用'K1 '? – AnT 2012-07-21 21:24:31

+0

@Tony Delroy我试过了你的确切代码,我仍然在我的comiler MVSC 2008 – Iam 2012-07-21 21:25:04

1

既然你的operator []除了参数类型都相同,为什么不模板呢?

template <typename TT> 
    const Property<T>& operator[](const TT& k) const 
    { 
     return _values[k.index()]; 
    } 
+0

因为我想更好地控制关键类型。我希望编译器不允许某些类型的键。 (只允许Key1和Key2) – Iam 2012-07-21 21:27:47

+1

@Iam:然后使用'enable_if'。没有重复代码的借口。 – 2012-07-21 21:38:38

+0

@CatPlusPlus:我宁愿倾向于“没有任何理由让它复杂化2线以上”,但每个都是属于自己的...... – 2012-07-21 21:46:36

1

您必须声明你index()功能const因为a_map模板中你是通过const对象

template<typename T> class key_a { 
public: 
    int index() const // <- `const` is necessary 
     { return _i; } 
private: 
    int _i; 
}; 

template<typename T> class key_b { 
public: 
    int index() const // <- `const` is necessary 
     { return 3; } 
}; 

但除此之外,一切都编译调用它们,我很好地工作。


在VS2010编译器中试过它,并得到与你一样的错误。这显然是MSVC++编译器中的一个编译器错误。处理模板模板参数的操作不正确。

要解决我能够使用这种技术

template< 
    typename T, 
    template<typename> class Property, 
    template<typename> class Key1, 
    template<typename> class Key2> 
class a_map 
{ 
public: 
    const Property<T>& operator[](const typename Key1<T>::self& k) const 
    { return _values[k.index()]; } 
    const Property<T>& operator[](const typename Key2<T>::self& k) const 
    { return _values[k.index()]; } 
protected: 
    std::vector<Property<T> > _values; 
}; 

的问题,并确定关键模板作为

template<typename T> class key_a { 
public: 
    typedef key_a self; 
    int index() const { return _i; } 
private: 
    int _i; 
}; 

template<typename T> class key_b { 
public: 
    typedef key_b self; 
    int index() const { return 3; } 
}; 

这是不雅,但它使用MSVC++编译器正常工作。