模板化运算符[] ......可能吗?有用?

时间:2010-03-04 17:11:46

标签: c++ templates

你能拥有:

template <class T>
const T &operator[] (unsigned int x)

我的想法是,如果你有一个map<string,string>,那么拥有一个可以让你做的包装类会更好:

obj["IntVal"]="12";
obj["StringVal"]="Test";

int i = obj["IntVal"];

我们在C ++中实际上可以接近这个吗?这值得痛苦吗?

6 个答案:

答案 0 :(得分:5)

您也可以

class Class {
  struct Proxy {
    template<typename T> T as() { ... }
    template<typename T> operator T() { return as<T>(); }
  private:
    Proxy(...) { ... }
    Proxy(Proxy const&); // noncopyable
    Proxy &operator=(Proxy const&);
    friend class Class;
  };

public:
  Proxy operator[](std::string const& s) { ... }
};

Class a;
int i = a["foo"];
int i = a["foo"].as<int>();

T将被推断为要初始化的对象。并且您不能复制代理。也就是说,我更喜欢明确的as<T>函数,就像另一个函数一样。

答案 1 :(得分:4)

你不能 - 在:

int i = obj["IntVal"]; 

由于返回类型不是函数签名的一部分,因此无法从上下文中推断出实际的T类型。

此外,由于内存和性能方面的考虑,将整数值存储为字符串不被视为最佳实践; - )

答案 2 :(得分:2)

不值得。

模板返回类型意味着您在调用时必须显式指定模板参数。像这样的东西,也许我的语法错了:

int i = obj.operator[]<int>("IntVal");

C ++不会从您分配调用结果的内容中推导出模板参数,只能从调用该函数的参数中推断出来。

所以你不妨定义一个正常的函数:

int i = obj.get<int>("IntVal");

或者在这种情况下,要么这样做,要么使用以下方法实现get

int i = boost:lexical_cast<int>(obj["IntVal"]);

正如Amit所说,您可以定义operator[]以返回可以转换为int或其他类型的类型。然后您的示例代码可以在没有显式lexical_cast的情况下进行编译。

答案 3 :(得分:0)

你看过boost variant了吗?这是你在找什么?

答案 4 :(得分:0)

嗯,你在示例代码中写的内容与问题不符。现在,你只有模板的返回类型。

但如果你想做类似的事情:

template <class T>
const T &operator[const T& x]

这是有效的,但可能不是非常有用。

答案 5 :(得分:0)

地图已经提供了一个重载的operator[],可以完成你想要的大部分工作。你似乎想要的东西是从一个恰好包含数字的字符串到一个整数的隐式转换。 C ++的一个基本特征是静态类型,它表示不应该允许 - 所以它不是。如果你愿意的话,它会很乐意进行转换,但你必须要求它:

int i = lexical_cast<int>(obj["IntVal"]);

或者,您可以创建一个类似字符串的类,支持隐式转换为int。就个人而言,我建议不要这样做。我并不反对隐含的转换几乎和许多人一样强烈,但这仍然让我觉得这是一个非常糟糕的想法,至少对于大多数人来说都是如此。