我有问题,因为在课堂上我想为不同类型的变量设置多个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
)。
有人有想法解决它吗?
答案 0 :(得分:0)
起初有些评论家:你公开的示例代码不是MCVE,并且留有很大的推测空间。 (这可能是所有这些下选票的一个原因。)
然而,由于这引起了我的注意,我想加2美分。
我完全同意scohe001和M.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[]()
调用提供了匹配的参数:
std::string("6")
operator[](const std::string&)
{li> 6L
operator[](long)
{li> 6.0
operator[](double)
'\6'
代表operator[](char)
char
,实际上不可打印。为了回到歧义问题的假设,我尝试了一些反例:
这有效:
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.
这失败了:
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
,则可以使用这些运算符。如上例所示,实际上有三个候选人 - 含糊不清。
回到第一个反例。我记得我曾经遇到过一个可怕的问题。
为了说明这一点,我将介绍另一个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上传了最终的源代码。