重载>>运算符并使用自定义类型的初始值设定项列表启动
Overloading >>operator and initiatializing using an initializer list of custom type
我一直在尝试制作一个非常简单的映射容器,我认为能够像这样初始化它会很好:
Hash table = { "name1" >> value,
"name2" >> value2,
"name3" >> value3,
"name4" >> value4 };
我打算如何做到这一点,首先制作一对(双人)数据结构保留每个元素的名称和值,重载>>运算符以使用名称和值参数返回一个duo,并为hash类创建一个构造函数来初始化它,方法是使用initializer_list来构造duo元素的向量。然后使用二进制搜索方法来检索所需的元素。
不幸的是,我从一开始就碰壁了。在我开始编码之前,我想确保重载被正确使用,事实上这是一个明智的决定,因为显然它们不是。
这项工作:
#include <iostream>
#include <string>
#include <vector>
#include <initializer_list>
struct duo {
duo(const std::string key,int value) :key(key) ,value(value) {};
const std::string key;
int value;
};
struct Hash {
std::vector<duo> lister;
Hash(std::initializer_list<duo> passed) :lister(passed) {};
};
duo operator >> (const std::string& id,int value) {
return duo(id,value);
}
int main(){
duo object1("test",1);
Hash table = {object1};
std::cout << table.lister[0].key << table.lister[0].value;
}
但这会将"const-char[6]和int类型的无效操作数赋予二进制运算符>>">
#include <iostream>
#include <string>
#include <vector>
#include <initializer_list>
struct duo {
duo(const std::string key,int value) :key(key) ,value(value) {};
const std::string key;
int value;
};
struct Hash {
std::vector<duo> lister;
Hash(std::initializer_list<duo> passed) :lister(passed) {};
};
duo operator >> (const std::string id,int value) {
return duo(id,value);
}
int main(){
Hash table = {"test1" >> 1};
std::cout << table.lister[0].key << table.lister[0].value;
}
我试图将std::string传递给>>运算符,因为我不能用基元类型重载。不过,这似乎不是一个解决方案。有没有任何方法可以在不显式地将字符串文字转换为std::string的情况下实现所需的效果?
显式构建string
将解决此问题:
int main(){
Hash table = {std::string("test1") >> 1};
std::cout << table.lister[0].key << table.lister[0].value;
}
我也会让>>
对常量字符串进行引用,而不是按值的字符串:
duo operator >> (const std::string& id,int value) {
return duo(id,value);
}
你可能认为你可以通过设计这样的东西来避免显式构造:
template <size_t N> duo operator >> (const char (&ary)[N], int id)
{
return duo (std::string (ary), id);
}
或:
duo operator >> (const char* id, int value)
{
return duo (std::string (id), value);
}
但是不能,因为C++不允许重写指针(或任何基元)类型的operator >>
。如果您尝试此操作,您将收到一个编译器错误,行为"必须具有类或枚举类型的参数"。为了提供运算符重载,您必须至少提供一个类或枚举型参数。
所以让我们思考一下。我们不能将operator<<
与两个基元参数一起使用,因为这是不允许的。您真正想要的是没有任何显式初始化的干净初始化语法。唯一真正阻碍我们的是初始化。那么,如果我们试图构建一个实际上使用两个运算符的东西,但看起来仍然干净呢?如果我们试图构建这样的东西:
Hash table = {"test1" <MapTo> 1};
它并不是您想要的语法,但它相当接近。因此,让我们尝试构建这个:
这里有两个操作员在工作:operator<
和operator>
。operator<
的参数是字符串文字"test1
和一些名为MapTo
的对象。operator>
的自变量是operator<
返回的任何值和一个整数字面值1
。
首先来看operator<
,让我们破解一个原型:
template <size_t N> std::string operator < (const char (&ary)[N], Something op)
我们知道我们希望operator>
返回duo
,那么Something
需要是什么才能实现这一点?我们真正需要operator<
做的就是将字符串文字转换为std::string
,所以让我们尝试一下:
class HashOperation
{
public:
template <size_t N> std::string cvt (const char (&ary)[N]) const
{
return std::string (ary);
}
} MapTo;
template <size_t N> std::string operator < (const char (&ary)[N], HashOperation op)
{
return op.cvt (ary);
}
现在我们有了std::string
,让我们将其与int.一起构建一个duo
duo operator> (const std::string& key, int value)
{
return duo (key, value);
}
这很容易。让我们把它放在一起(现场演示):
#include <iostream>
#include <string>
#include <vector>
#include <initializer_list>
struct duo {
duo(const std::string key,int value) :key(key) ,value(value) {};
template <size_t N> duo (const char (&ary)[N], int value) : key (ary), value (value) {};
const std::string key;
int value;
};
struct Hash {
std::vector<duo> lister;
Hash(std::initializer_list<duo> passed) :lister(passed) {};
};
class HashOperation
{
public:
template <size_t N> std::string cvt (const char (&ary)[N]) const
{
return std::string (ary);
}
} MapTo;
template <size_t N> std::string operator < (const char (&ary)[N], HashOperation op)
{
return op.cvt (ary);
}
duo operator> (const std::string& key, int value)
{
return duo (key, value);
}
int main(){
Hash table =
{
"test1" <MapTo> 1,
"test2" <MapTo> 2
};
std::cout << table.lister[0].key << table.lister[0].value;
}
您正试图为两个基元类型char const *
和int
重载operator>>
;这是语言不允许的。要使其以当前形式工作,您需要从第一个参数显式创建一个std::string
Hash table = {std::string("test1") >> 1};
当然,另一种选择是在初始化时放弃这种语法,而坚持使用逗号分隔的对。
#include <iostream>
#include <string>
#include <vector>
#include <initializer_list>
#include <utility>
using duo = std::pair<std::string, int>;
struct Hash {
std::vector<duo> lister;
Hash(std::initializer_list<duo> passed) :lister(passed) {};
};
int main(){
Hash table = {{"test1", 1}, {"test2", 2}};
std::cout << table.lister[0].first << table.lister[0].second;
}
您为std::string和int定义了运算符>>,但您试图将其与参数const char[]和int一起使用。您需要让编译器知道第一个参数是std::字符串。尝试{"test1"s >> 1}
- Pybind11:将元组列表从Python传递到C++
- 从链接列表c++中删除一个项目
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++如何通过用户输入删除列表元素
- 读取文件的最后一行并输入到链接列表时出错
- 复制列表初始化的隐式转换的等级是多少
- LNK2038、MSVS2017 MAGMA的原因列表
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 没有为自己的结构调用列表推回方法
- 使用简单类型列表实现的指数编译时间.为什么
- 一对向量构造函数:初始值设定项列表与显式构造
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 通过for循环使用用户输入填充列表
- C++:如何使函数只返回作为列表一部分的字符串
- 概念中的cv限定符需要表达式参数列表
- 下面是我为检测链接列表中的循环而制作的代码
- 建议在运行时将带有类实例的列表从c++导入qml
- 如何维护资源管理器项目视图中当前可见的项目列表
- EASTL矢量<向量<int>>连续的
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改