C++ 中 [] 的可变运算符重载
Variadic operator overloading of the [] in C++
我希望使用运算符 [] 中传递的表达式。我认为使用可变模板参数可以解决问题,但我错了......
在 c++11 中有办法做到这一点吗?
class object {
private:
public:
void values() { std::cout << "finished" << std::endl; }
template <typename T, typename... Type> void values(T arg, Type... args) {
std::cout << arg << " " << std::endl;
values(args...);
}
template<typename... Type> void operator[](Type... args) {
values(args...);
}
};
int main(void) {
object o1 = object();
o1.values(1, 6.2, true, "hello"); // Works fine.
o1[1, 6.2, true]; // Only the last value gets printed eg. true
return 0;
}
更广泛的objective是我被要求制作一个工作语法
let o3 = object [ values 1, "2", true, -3.14 ];
let o1 = object [ key("x") = -1, key("y") = -2,values 1, "2", true, -3.14 ]; // no commas are missing
在 c++11 中使用 c++11 STL(模板、using、MACROS、运算符重载等)。我正在慢慢想办法把它拼凑起来
首先,你需要明白operator[]
只能接受一个参数。您的模板化运算符隐藏了一条非常清楚的错误消息。
struct foo {
void operator[](int,int);
};
结果错误:
<source>:2:10: error: 'void foo::operator[](int, int)' must have exactly one argument
2 | void operator[](int,int);
| ^~~~~~~~
您可以将其设为可变参数模板,但任何不完全包含一个参数的实例化都是不正确的。
F运行ky,这听起来像是一个骗人的问题。编写 C++ 代码时,最好使用 C++ 语法。如果允许宏(它们不应该),那么几乎任何事情都是可能的。您只需要知道您实际上不再是在编写 C++。此外,仅仅要求编译一些语法似乎有点奇怪。我不知道 javascript 也不确定这两行是什么意思,所以我只是这样做了:让它以某种方式编译。
总之,让我们看看能做些什么。
let o3 = object [ values 1, "2", true, -3.14 ];
我想这会将 o3
声明为一个对象,其初始值设定项是从名为 object
的容器中检索的,可以通过 values 1, "2", true, -3.14
进行索引。可以通过重载一些 operator,
和 #define
使 let
成为 auto
和 values
来编译该行以构造一个收集索引的对象(通过它的 operator,
):
第二行
let o1 = object [ key("x") = -1, key("y") = -2,values 1, "2", true, -3.14 ];
可以用 operator,
和滥用 key::operator=
玩类似的把戏。我将 key
解释为构造一些键值对,例如 key("x") = -1
将值 -1
映射到字符串 "x"
。它实际所做的对于随后的所有脏东西来说并不是必不可少的。一旦您了解了如何滥用运算符重载,就可以对其进行修改以在细节中执行其他操作。
为了看到所有值实际上都传递给 operator[]
我从这里偷了一些元组打印函数:
#include <tuple>
#include <string>
#include <typeinfo>
#include <iostream>
#define let auto
//
template<class TupType, size_t... I>
void print(const TupType& _tup, std::index_sequence<I...>)
{
std::cout << "(";
(..., (std::cout << (I == 0? "" : ", ") << std::get<I>(_tup)));
std::cout << ")\n";
}
template<class... T>
void print (const std::tuple<T...>& _tup)
{
print(_tup, std::make_index_sequence<sizeof...(T)>());
}
//........................................
struct Object {
template <typename ...T>
struct ObjectIndex {
ObjectIndex() {}
ObjectIndex(std::tuple<T...> ind) : index(ind) {}
std::tuple<T...> index;
template <typename U>
ObjectIndex<T...,U> operator,(const U& u){
return { std::tuple_cat(index,std::make_tuple(u)) };
}
template <typename...U>
ObjectIndex<T...,U...> operator,(const ObjectIndex<U...>& other) {
return { std::tuple_cat(index,other.index) };
}
};
template <typename ...T>
int operator[](ObjectIndex<T...> index){
std::cout << typeid(index.index).name() << "\n";
print(index.index);
return 42;
}
};
struct key {
std::string k;
int val;
key(const std::string& s) : k(s) {}
Object::ObjectIndex<std::string,int> operator=(int v) {
val = v;
return {std::make_tuple(k,val)};
}
};
#define values Object::ObjectIndex<>{} ,
int main() {
Object object;
let o3 = object [ values 1, std::string("2"), true, -3.14 ];
let o1 = object [ key("x") = -1, key("y") = -2,values 1, std::string("2"), true, -3.14 ];
}
不要在家里(或其他任何地方)这样做!
传递字符串文字时出现了一些问题,我没有费心去进一步研究,所以我允许自己将 "2"
替换为 std::string("2")
。我想通过无休止的错误消息进行更多的斗争也可以解决这个问题。
我不知道代码是否接近这两行真正应该做的事情。我只是把它当作一个有趣的练习来让它以某种方式编译。当实际从 operator[]
返回一些东西时,我 运行 没有想法。我很难想象一个具有真正可变参数 operator[]
的容器。我总是选择正确的答案。
TL;DR 你能重载 operator[]
以获取多个参数吗?不可以。您可以重载它以采用封装任意值的单个参数吗?当然。
我希望使用运算符 [] 中传递的表达式。我认为使用可变模板参数可以解决问题,但我错了...... 在 c++11 中有办法做到这一点吗?
class object {
private:
public:
void values() { std::cout << "finished" << std::endl; }
template <typename T, typename... Type> void values(T arg, Type... args) {
std::cout << arg << " " << std::endl;
values(args...);
}
template<typename... Type> void operator[](Type... args) {
values(args...);
}
};
int main(void) {
object o1 = object();
o1.values(1, 6.2, true, "hello"); // Works fine.
o1[1, 6.2, true]; // Only the last value gets printed eg. true
return 0;
}
更广泛的objective是我被要求制作一个工作语法
let o3 = object [ values 1, "2", true, -3.14 ];
let o1 = object [ key("x") = -1, key("y") = -2,values 1, "2", true, -3.14 ]; // no commas are missing
在 c++11 中使用 c++11 STL(模板、using、MACROS、运算符重载等)。我正在慢慢想办法把它拼凑起来
首先,你需要明白operator[]
只能接受一个参数。您的模板化运算符隐藏了一条非常清楚的错误消息。
struct foo {
void operator[](int,int);
};
结果错误:
<source>:2:10: error: 'void foo::operator[](int, int)' must have exactly one argument
2 | void operator[](int,int);
| ^~~~~~~~
您可以将其设为可变参数模板,但任何不完全包含一个参数的实例化都是不正确的。
F运行ky,这听起来像是一个骗人的问题。编写 C++ 代码时,最好使用 C++ 语法。如果允许宏(它们不应该),那么几乎任何事情都是可能的。您只需要知道您实际上不再是在编写 C++。此外,仅仅要求编译一些语法似乎有点奇怪。我不知道 javascript 也不确定这两行是什么意思,所以我只是这样做了:让它以某种方式编译。
总之,让我们看看能做些什么。
let o3 = object [ values 1, "2", true, -3.14 ];
我想这会将 o3
声明为一个对象,其初始值设定项是从名为 object
的容器中检索的,可以通过 values 1, "2", true, -3.14
进行索引。可以通过重载一些 operator,
和 #define
使 let
成为 auto
和 values
来编译该行以构造一个收集索引的对象(通过它的 operator,
):
第二行
let o1 = object [ key("x") = -1, key("y") = -2,values 1, "2", true, -3.14 ];
可以用 operator,
和滥用 key::operator=
玩类似的把戏。我将 key
解释为构造一些键值对,例如 key("x") = -1
将值 -1
映射到字符串 "x"
。它实际所做的对于随后的所有脏东西来说并不是必不可少的。一旦您了解了如何滥用运算符重载,就可以对其进行修改以在细节中执行其他操作。
为了看到所有值实际上都传递给 operator[]
我从这里偷了一些元组打印函数:
#include <tuple>
#include <string>
#include <typeinfo>
#include <iostream>
#define let auto
//
template<class TupType, size_t... I>
void print(const TupType& _tup, std::index_sequence<I...>)
{
std::cout << "(";
(..., (std::cout << (I == 0? "" : ", ") << std::get<I>(_tup)));
std::cout << ")\n";
}
template<class... T>
void print (const std::tuple<T...>& _tup)
{
print(_tup, std::make_index_sequence<sizeof...(T)>());
}
//........................................
struct Object {
template <typename ...T>
struct ObjectIndex {
ObjectIndex() {}
ObjectIndex(std::tuple<T...> ind) : index(ind) {}
std::tuple<T...> index;
template <typename U>
ObjectIndex<T...,U> operator,(const U& u){
return { std::tuple_cat(index,std::make_tuple(u)) };
}
template <typename...U>
ObjectIndex<T...,U...> operator,(const ObjectIndex<U...>& other) {
return { std::tuple_cat(index,other.index) };
}
};
template <typename ...T>
int operator[](ObjectIndex<T...> index){
std::cout << typeid(index.index).name() << "\n";
print(index.index);
return 42;
}
};
struct key {
std::string k;
int val;
key(const std::string& s) : k(s) {}
Object::ObjectIndex<std::string,int> operator=(int v) {
val = v;
return {std::make_tuple(k,val)};
}
};
#define values Object::ObjectIndex<>{} ,
int main() {
Object object;
let o3 = object [ values 1, std::string("2"), true, -3.14 ];
let o1 = object [ key("x") = -1, key("y") = -2,values 1, std::string("2"), true, -3.14 ];
}
不要在家里(或其他任何地方)这样做!
传递字符串文字时出现了一些问题,我没有费心去进一步研究,所以我允许自己将 "2"
替换为 std::string("2")
。我想通过无休止的错误消息进行更多的斗争也可以解决这个问题。
我不知道代码是否接近这两行真正应该做的事情。我只是把它当作一个有趣的练习来让它以某种方式编译。当实际从 operator[]
返回一些东西时,我 运行 没有想法。我很难想象一个具有真正可变参数 operator[]
的容器。我总是选择正确的答案。
TL;DR 你能重载 operator[]
以获取多个参数吗?不可以。您可以重载它以采用封装任意值的单个参数吗?当然。