c++ - 模板映射的设计问题采用不同的结构

标签 c++ dictionary templates

问题描述和问题

我有一个模板Class1。它包含在 map 中,我想在其中插入结构 AB

问题在于结构AB 具有不同类型的成员变量。结构 A 有一个 std::string 成员变量,而结构 B 有一个 int 成员变量。

比较器基于结构A。所以很明显,当我想插入一个结构 B 时,它不会编译。

Class1<B,B> c2;
c2.AddElement({1},{1});

我该如何解决该设计问题?例如,是否可以将 Class1 保留为 template 类并对 TestCompare 做一些事情?

我也有一个约束。我不能修改结构AB。它们是用 C 代码编写的。我无权更改它们,因为它们是其他用户使用的外部代码。我只是尽可能地简化了代码。


源代码

代码编译于cpp.sh

#include <iostream>
#include <string>
#include <map>

typedef struct {
    std::string a;
} A;

typedef struct {
    int b;
} B;


template<typename T1, typename T2> class Class1 {
    public :
      struct TestCompare {
         bool operator()(const T1 & lhs, const T1 & rhs) const {
        return lhs.a < rhs.a;
         }
       };
       Class1() {}
       ~Class1() {}
       void AddElement(const T1 & key, const T2 & value) {
          m.emplace(key, value);
        }
    private :
     std::map<T1,T2,TestCompare> m;
};

int main()
{
  Class1<A,A> c1;
  c1.AddElement({"1"},{"1"});
  
  // Problem here. Obviously it will not compile because the Operator is using 
  // the member variable of struct A.
  //Class1<B,B> c2;
  //c2.AddElement({1},{1});
  //return 0;
}

新源代码

 // Example program
#include <iostream>
#include <string>
#include <map>

typedef struct {
    std::string a;
} A;

typedef struct {
    int b;
} B;


bool operator<(const A & lhs, const A & rhs) {
    return lhs.a < rhs.a;
}

bool operator<(const B & lhs, const B & rhs) {
    return lhs.b < rhs.b;
}

template<typename T1, typename T2> class Class1 {
    public :
    Class1() {}
    ~Class1() {}
    void AddElement(const T1 & key, const T2 value) {
        m.emplace(key, value);
    }
    
     std::map<T1,T2> getMap() {
        return m;
    }
    
    private :
     std::map<T1,T2> m;
};

int main()
{
  Class1<A,A> c1;
  c1.AddElement({"1"},{"1"});
  
  // Problem here. Obviously it will not compile because the Operator is using 
  // the member variable of struct A.
  Class1<B,B> c2;
  c2.AddElement({1},{1});
  c2.AddElement({2},{2});
  
  for(const auto &e: c2.getMap()) {
      std::cout << e.first.b << " " << e.first.b << std::endl;
  }
  return 0;
}

最佳答案

我想您可以从 Class1 中删除 TestCompare 并为其创建模板。

template<typename T> struct TestCompare {
    bool operator()(const T & lhs, const T & rhs) const {
        // default implementation
        return lhs < rhs;
    }
};

template<typename T1, typename T2> class Class1 {
     ...
    private :
     std::map<T1,T2,TestCompare<T1>> m;
}

然后您可以针对 AB 专门化 TestCompare

template<> struct TestCompare<A> {
    bool operator()(const A & lhs, const A & rhs) const {
        return lhs.a < rhs.a;
    }
};

template<> struct TestCompare<B> {
    bool operator()(const B & lhs, const B & rhs) const {
        return lhs.b < rhs.b;
    }
};

编辑: 实际上,您可以只使用 std::less 而不是 TestCompare。这几乎是一回事,std::map 默认使用 std::less

关于c++ - 模板映射的设计问题采用不同的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51453798/

相关文章:

python - 在 Python 中加载字典最有效的方法是什么?

python - 从列表 Python 中向字典添加键

c++ - C++中的字典/哈希表对象?

c# - 拉伸(stretch)不适用于 WPF 模板化按钮

c# - 创建和动态使用内容模板和控件

c++ - 带结构的模板

c++ - 编译时检查方法是否定义为虚拟

c# - 了解有关分布式计算的更多信息

c++ - 使用带有接口(interface)和新语法的 Qt 连接时出错

c++ - 如何生成第n个只有偶数位的数?