在返回的模板化类中进行参数推断

时间:2016-06-23 14:05:20

标签: c++

我想实施以下课程:

class A
{
public:
    template<typename VAL_TYPE>
    class PP {
    public:
        PP();
        void init(const string &name);

        operator VAL_TYPE();
        VAL_TYPE & operator = (const VAL_TYPE&);

    private:
        string _name;
        VAL_TYPE _val;

        void getter();
        void setter();

    };

    A();
public:    
    template<typename VAL_TYPE>
    PP<VAL_TYPE>& operator[](const string& name);

private:
    PP<int> _pp_int;
    PP<double> _pp_float;
    PP<string> _pp_string;
};

gettersetter方法在.cpp文件中实现,用于&#39; int&#39;,&#39; double&#39;和&#39;字符串&#39;类型分开:

void A::PP<int>::setter()
{
   ...
}
void A::PP<int>::getter()
{
   ...
}

以及&#39; double&#39;等等和&#39;字符串&#39;类型。

问题是关于重载的A :: operator []。 它应该返回P<int>(_pp_int成员)或PP<double>(_pp_float成员)或PP<string>(_pp_string成员) 名称&#39;的价值参数。目的是使用这样的东西:

A a;

a["iii"] = 10;
int i = a["iii"];

a["ddd"] = 3.141519;
double d = a["ddd"];

a["sss"] = "string";
string s = a["sss"];

据我所知,这是一个大问题:编译器如何在A :: operator []中推导出模板参数VAL_TYPE

有可能实现这样的想法吗? 我阅读了很多帖子,但仍然找不到任何解决方案。

可能在Qt库的框架中可以吗?

1 个答案:

答案 0 :(得分:1)

你最容易接近的是:

#include <boost/variant.hpp>

#include <string>
#include <unordered_map>

using Map = std::unordered_map<std::string, boost::variant<std::string, int, double> >;

int main()
{
  Map m;
  m["iii"] = 5;
  int i = boost::get<int>(m["iii"]);
  m["ddd"] = 0.3;
  double d = boost::get<double>(m["ddd"]);
  m["sss"] = "hello";
  std::string s = boost::get<std::string>(m["sss"]);
  return 0;
}

此代码可以运行并执行您想要的操作。 boost变量是一个“sum”类型,它只包含一个对象,它具有模板化的一种类型。换句话说,这里它们包含字符串,整数或双精度。

当赋予boost变量时,它将根据指定的类型进行类型推断并执行正确的操作。但它没有办法轻松地为所有类型提供隐式转换。所以你必须明确提取值。坦率地说,我建议只是按原样使用它并与它一起生活,但我确定你没有听到这样的消息,所以...

在您的特定情况下,如果您愿意放弃通用性,则可以执行此操作。基本上,您只需编写一个包含boost变体的类,但您也可以为其添加隐式转换。

class PP {
public:
  // forward heterogeneous assignment etc so that works as before

  operator std::string() { return boost::get<string>(m_data); }
  // similar for other types
private:
  boost::variant<std::string, int, double> m_data;
}

现在,当您尝试将PP分配给字符串时,将没有直接赋值,但编译器将看到PP提供了对字符串的隐式转换并使用它。 / p>

问题是,这在语言复杂性方面打开了一大堆蠕虫,并不值得。它应该实际上是通过引用提供转换,通过引用,关于constness,rvalues等等。还有值得考虑的是boost::get如果变量不包含所请求的类型,将非常大声地(通过抛出)失败,所以你现在有一种情况,无辜的分配操作很容易抛出。我建议学习一下boost变体(它可能会很快成为标准的一部分,它已被大量讨论)并学习了一些在那里使用的技术,比如访问者。它们起初可能是外来的,但是它们工作得很好,它们发挥C ++的优势,而不是试图让C ++表现得像python。