C ++类operator []不同类型的变量(double,int,char,string)

时间:2018-01-05 00:46:39

标签: c++

我有问题,因为在课堂上我想为不同类型的变量设置多个operator[]

 type operator[](const std::string val);
 //type operator[](const long int val);
 type operator[](const double val);
 //type operator[](const char val);

但这种方式是错误的,因为编译器返回多个声明的错误(char,int和double是“相同的”变量)。只有评论了2个职位,计划才有效。但是,如果我使用带有operator[]字母的'a',则会使用operator[](double)'a'成为97.000000)。

有人有想法解决它吗?

1 个答案:

答案 0 :(得分:0)

起初有些评论家:你公开的示例代码不是MCVE,并且留有很大的推测空间。 (这可能是所有这些下选票的一个原因。)

然而,由于这引起了我的注意,我想加2美分。

我完全同意scohe001M.M - 暴露的声明不是问题。

如果operator[]()与不完全匹配类型的参数一起使用,则会出现问题。

演示:

#include <iostream>
#include <set>
#include <sstream>
#include <string>

// trying to resemble the OP

template <typename VALUE>
class MultiAccessorT {
  public:
    typedef VALUE Value;
    typedef std::set<Value> Table;
  private:
    Table &_tbl;
  public:
    MultiAccessorT(Table &tbl): _tbl(tbl) { }

    typename Table::iterator operator[](const std::string &str)
    {
      std::cout << "using operator[](const std::string&) ";
      std::istringstream cvt(str);
      Value value;
      return cvt >> value ? _tbl.find(value) : _tbl.end();
    }

    typename Table::iterator operator[](long value)
    {
      std::cout << "using operator[](long) ";
      return _tbl.find((Value)value);
    }

    typename Table::iterator operator[](double value)
    {
      std::cout << "using operator[](double) ";
      return _tbl.find((Value)value);
    }

    typename Table::iterator operator[](char value)
    {
      std::cout << "using operator[](char) ";
      return _tbl.find((Value)value);
    }
};

// checking out

int main()
{
  // build some sample data
  std::set<unsigned> tbl = { 0, 2, 4, 6, 8, 10, 12, 14 };
  // template instance and instance
  MultiAccessorT<unsigned> acc(tbl);
  // test the operators
  std::cout << "MultiAccessorT::operator[](const string&): ";
  std::cout << (acc[std::string("6")] != tbl.end() ? "found." : "missed!") << std::endl;
  std::cout << "MultiAccessorT::operator[](long): ";
  std::cout << (acc[6L] != tbl.end() ? "found." : "missed!") << std::endl;
  std::cout << "MultiAccessorT::operator[](double): ";
  std::cout << (acc[6.0] != tbl.end() ? "found." : "missed!") << std::endl;
  std::cout << "MultiAccessorT::operator[](char): ";
  std::cout << (acc['\6'] != tbl.end() ? "found." : "missed!") << std::endl;
  // done
  return 0;
}

我在cygwin上用g ++编译并测试了它:

$ g++ --version
g++ (GCC) 6.4.0

$ g++ -std=c++11 -o test-polymorphy test-polymorphy.cc 

$ ./test-polymorphy
MultiAccessorT::operator[](const string&): using operator[](const std::string&) found.
MultiAccessorT::operator[](long): using operator[](long) found.
MultiAccessorT::operator[](double): using operator[](double) found.
MultiAccessorT::operator[](char): using operator[](char) found.

$

为了防止歧义(可能会破坏代码),我小心地为MultiAccessorT::operator[]()调用提供了匹配的参数:

    {li> std::string("6") operator[](const std::string&) {li> 6L operator[](long) {li> 6.0 operator[](double)
  • '\6'代表operator[](char)
    反斜杠对八进制数进行编码,以实现值{6的char,实际上不可打印。

为了回到歧义问题的假设,我尝试了一些反例:

  1. 这有效:

    std::cout << "using a constant string \"6\" (type const char[2]) ";
    std::cout << (acc["6"] != tbl.end() ? "found." : "missed!") << std::endl;

    输出是:

    using a constant string "6" (type const char[2]) using operator[](const std::string&) found.
  2. 这失败了:

    std::cout << "using an int constant 6";
    std::cout << (acc[6] != tbl.end() ? "found." : "missed!") << std::endl;

    g ++抱怨道:

    test-polymorphy.cc: In function 'int main()':
    test-polymorphy.cc:66:24: error: ambiguous overload for 'operator[]' (operand types are 'MultiAccessorT' and 'int')
       std::cout << (acc[6] != tbl.end() ? "found." : "missed!") << std::endl;
                        ^
    test-polymorphy.cc:26:34: note: candidate: typename MultiAccessorT::Table::iterator MultiAccessorT::operator[](long int) [with VALUE = unsigned int; typename MultiAccessorT::Table::iterator = std::_Rb_tree_const_iterator]
         typename Table::iterator operator[](long value)
                                  ^~~~~~~~
    test-polymorphy.cc:32:34: note: candidate: typename MultiAccessorT::Table::iterator MultiAccessorT::operator[](double) [with VALUE = unsigned int; typename MultiAccessorT::Table::iterator = std::_Rb_tree_const_iterator]
         typename Table::iterator operator[](double value)
                                  ^~~~~~~~
    test-polymorphy.cc:38:34: note: candidate: typename MultiAccessorT::Table::iterator MultiAccessorT::operator[](char) [with VALUE = unsigned int; typename MultiAccessorT::Table::iterator = std::_Rb_tree_const_iterator]
         typename Table::iterator operator[](char value)
                                  ^~~~~~~~
    

    我们在这里。由于没有完全匹配的operator[](int),编译器会查找可能的运算符,如果将隐式转换应用于int,则可以使用这些运算符。如上例所示,实际上有三个候选人 - 含糊不清。

  3. 回到第一个反例。我记得我曾经遇到过一个可怕的问题。

    为了说明这一点,我将介绍另一个operator[]()

        // This resembles my personal "hair-killer":
        typename Table::iterator operator[](bool value)
        {
          std::cout << "using operator[](bool) ";
          return value ? _tbl.begin() : _tbl.end();
        }
    

    再次编译并运行:

    $ g++ -std=c++11 -o test-polymorphy test-polymorphy.cc 
    
    $ ./test-polymorphy
    MultiAccessorT::operator[](const string&): using operator[](const std::string&) found.
    MultiAccessorT::operator[](long): using operator[](long) found.
    MultiAccessorT::operator[](double): using operator[](double) found.
    MultiAccessorT::operator[](char): using operator[](char) found.
    using a constant string "6" (type const char[2]) using operator[](bool) found.
    
    $
    
    嗯,什么!? using operator[](bool)

    首先,没有抱怨的含糊不清。其次,它优先于bool而不是std::string?怎么来的?

    根据C ++标准,这是真正定义的行为。 bool是主要类型 - class std::string不是。字符串常量"6"被编译为类型为const char[2]的数据 - 一个数组。数组不能作为参数传递 - 它们在这种情况下隐含地衰减为指针,即它变为const char*。现在,编译器检查可用的运算符(在第一轮中使用主要参数类型),并且只有一个匹配:operator[](bool)。另一个匹配operator[](const std::string&)甚至没有被识别,因为在找到明确的&#34;命中后,它不会开始第二轮(包括编程类型的扩展搜索)。在第一个。

    这是几年前发生在我身上的事。起初,我甚至没有认识到它,但经过一段时间的测试后,我意识到某些细节在某种程度上是错误的。深入挖掘我终于发现了这个问题。 (这次我非常努力地打击了我 - 可能是我失去了一些头发的责任。)

    最后但并非最不重要的是,我已在ideone.com上传了最终的源代码。