代码之家  ›  专栏  ›  技术社区  ›  DougN

困在C++模板上-从std::map派生

  •  0
  • DougN  · 技术社区  · 17 年前

    我将扩展现有的std::map类,并向其中添加一个新函数:

    template<typename key_type, typename value_type>
    class CleanableMap : public Cleanable, public std::map<key_type, value_type> 
    {
        CleanableMap(const CleanableMap& in); //not implemented
        CleanableMap& operator=(const CleanableMap& in); //not implemented
    public:
        CleanableMap() {}
        CleanableMap(const std::map<key_type, value_type>& in) { *this = in; }
        virtual ~CleanableMap() {}
        std::map<key_type, value_type>& operator=(const std::map<key_type, value_type>& in)
        {
            *((std::map<key_type, value_type>*)this) = in;
            return *this;
        }
    };
    

    我有一个复制构造函数和赋值运算符,这样我就可以简单地将同一类型的现有std::map赋值给我的新map:

    CleanableMap<DWORD, DWORD> cm;
    std::map<DWORD, DWORD> stdm;
    cm = stdm;
    

    1>c:\dev\proj\commonfunc.cpp(399) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::map<_Kty,_Ty>' (or there is no acceptable conversion)
    1>        with
    1>        [
    1>            _Kty=DWORD,
    1>            _Ty=DWORD
    1>        ]
    1>        c:\dev\proj\templates.h(245): could be 'CleanableMap<key_type,value_type> &CleanableMap<key_type,value_type>::operator =(const CleanableMap<key_type,value_type> &)'
    1>        with
    1>        [
    1>            key_type=DWORD,
    1>            value_type=DWORD
    1>        ]
    1>        c:\dev\proj\templates.h(250): or       'std::map<_Kty,_Ty> &CleanableMap<key_type,value_type>::operator =(const std::map<_Kty,_Ty> &)'
    1>        with
    1>        [
    1>            _Kty=unsigned long,    <--- where did it come up with that?
    1>            _Ty=std::pair<const DWORD,DWORD>,  <--- where did it come up with that?
    1>            key_type=DWORD,
    1>            value_type=DWORD
    1>        ]
    1>        while trying to match the argument list '(CleanableMap<key_type,value_type>, std::map<_Kty,_Ty>)'
    1>        with
    1>        [
    1>            key_type=DWORD,
    1>            value_type=DWORD
    1>        ]
    1>        and
    1>        [
    1>            _Kty=DWORD,
    1>            _Ty=DWORD
    1>        ]
    

    第245行提到的“可能”没有意义——没有这样的赋值运算符(好吧,它是私有的。完全删除它不会改变任何事情)。

    它在第250行提到的“可能是”是我定义的赋值运算符,但不知何故,它推断出了一些其他不匹配的模板类型。它从哪里弄来的??

    救命!!! :)

    5 回复  |  直到 17 年前
        1
  •  16
  •   JaredPar    17 年前

    补充尼尔的回答。

    std::map<int,int>* pMap = GetCleanableMap();
    ...
    delete pMap; // does not call your destructor
    
        2
  •  12
  •   curiousguy    13 年前

    std::map

        3
  •  4
  •   Potatoswatter    16 年前

    很多人反对STL对象的继承。不过,您可以通过使用访问保护来使该过程更安全:使用 map 作为一个私人基地。这是一个演示。

    #include <iostream>
    #include <map>
    
    using namespace std;
    
    struct cmap : private map<int, int> {
            cmap() : map<int, int>() { };
    
            using map<int, int>::operator[]; // repeat for other methods you'd like
    };
    
    int main( int argc, char **argv ) {
            cmap my_map;
    
            my_map[1] = 2; // behaves like a map
    
            cerr << my_map[1] << " " << my_map[2] << endl;
    
            // map<int, int> *bad_map = &my_map; this does not compile
    
            return 0;
    }
    
        4
  •  2
  •   Michael Kohne    14 年前

    您遇到的可能是您的环境中std::map的确切实现的工件。由于std::map从未打算从中派生出来,因此实现通常要么有奇怪的专门化,要么有看起来奇怪的内部结构,这有助于使它们更快,但如果你试图从中派生,会导致许多奇怪的错误。

    或者,你的另一个基类可能有一些奇怪之处——“Cleanable”是什么样子的?如果你删除了“可清理”基(作为测试),其他所有东西都会编译吗?他们的名字可能会有一些奇怪的内部冲突吗?

        5
  •  1
  •   neverlord    17 年前
    std::map<key_type, value_type>& operator=(const std::map<key_type, value_type>& in)
    {
        *((std::map<key_type, value_type>*)this) = in;
        return *this;
    }
    

    =运算符的正确签名应该是:

    CleanableMap &operator=(const std::map<key_type, value_type> &in);
    

    template<typename K, typename V> void clean(std::map<K, V> &map);
    

    正如JaredPar所说,应该避免从具有非虚析构函数的类中派生。

    使用包装器或函数。