[英]Passing function and operator calls in object
I am wanting to make a class which allows me to lock an object from being modified. 我想创建一个类,使我可以锁定对象,以免被修改。 It would essentially be a template with a boolean specifying the lock state.
它本质上是一个带有布尔值的模板,用于指定锁定状态。 Since it is a template, I won't know all the methods that can be called on the internal object, so I need a method to pass calls through...
因为它是模板,所以我不知道可以在内部对象上调用的所有方法,所以我需要一个方法来传递调用。
template<class T>
class const_lock
{
public:
const_lock() : my_lock(false) {}
void set_const_lock(bool state) {my_lock = state;}
// HOW TO IMPLEMENT SOMETHING LIKE THESE????
//
template<typename...Args >
auto operatorANY_OPERATOR (Args...args)
{
if(my_lock != false)
throw std::exception("Objected locked to modification");
return my_value.ANY_OPERATOR(args);
}
template<typename...Args >
auto operatorANY_CONST_OPERATOR (Args...args) const
{
return my_value.ANY_CONST_OPERATOR(args);
}
template<typename...Args >
auto ANY_METHOD(Args...args)
{
if(my_lock != false)
throw std::exception("Objected locked to modification");
return my_value.ANY_METHOD(args);
}
template<typename...Args >
auto ANY_CONST_METHOD(Args...args) const
{
return my_value.ANY_CONST_METHOD(args);
}
private:
bool my_lock;
T my_value;
}
int main()
{
const_lock<std::vector<int>> v;
v.push_back(5);
v.push_back(7);
v.set_const_lock(true);
v.push_back(9); // fails compilation
std::cout << v.at(1) << std::endl; // ok
}
Any help would be appreciated. 任何帮助,将不胜感激。 Thanks!
谢谢!
Edit: changed static assert to throw and exception 编辑:将静态断言更改为throw和exception
What you're trying to do looks rather difficult, but more importantly is over-complicated and unnecessary for what you're trying to do. 您尝试做的事情看起来相当困难,但是更重要的是,对于您尝试做的事情来说过于复杂和不必要。
Essentially what you're trying to do (correct me if I'm wrong) is create a compile time check of whether you are supposed to able to modify an object at a given time. 从本质上讲,您要尝试进行的操作(如果我错了,请纠正我)是创建编译时检查,以检查是否应该在给定的时间修改对象。 However, c++ already has a built in way of doing this.
但是,c ++已经具有执行此操作的内置方法。 Simply declare or pass your object as const or const&, and the compiler will not allow you to modify non-mutable parts of the object.
只需将您的对象声明为const或const&即可,编译器将不允许您修改对象的非可变部分。 When you want to be able to modify it pass it without const.
当您希望能够对其进行修改时,可以不带const进行传递。 You can even cast it from const& to regular & when you want to go from code where you can't modify it directly to code where you can, though I don't recommend it.
您甚至可以将其从const&强制转换为常规&,而您想从无法直接修改它的代码转到可以的代码中,尽管我不建议这样做。
edit: just saw a comment on the question about no reference arrays. 编辑:刚刚看到关于没有引用数组的问题的评论。 Don't worry about that!
不用担心! The standard library has support for reference wrappers which allow you to essentially store references in arrays or anywhere else.
标准库支持引用包装,使您可以将引用本质上存储在数组或其他任何位置。
You can make a generic wrapper class that you can forward the function to using a lambda that captures a reference to the internal member. 您可以创建一个通用包装器类,然后将其转发给使用捕获内部成员引用的lambda函数。 In this example I am just using an if statement to check if it is "locked" and if it is then we just modify a copy.
在这个例子中,我只是使用一个if语句来检查它是否被“锁定”,如果是,那么我们只是修改一个副本。
template<class T>
class const_lock
{
private:
bool my_lock;
mutable T my_value;
public:
const_lock() : my_lock(false) {}
void set_const_lock() { my_lock = true; }
template<typename F>
auto operator()(F f) const -> decltype(f(my_value))
{
if (my_lock)
{
T temp{my_value}; // make a copy
return f(temp);
}
else
return f(my_value); // modify wrraped value
}
};
int main()
{
const_lock<std::string> cl;
cl([](std::string& s) {
s = "foobar";
});
cl([](std::string& s) {
std::cout << s << std::endl;
});
cl.set_const_lock();
cl([](std::string& s) {
s = "we should still be foobar";
});
cl([](std::string& s) {
std::cout << s;
});
}
This is completely unimplementable. 这是完全无法实现的。 A trivial modification of your source code shows why this won't work.
对源代码进行小小的修改就可以说明为什么它不起作用。
int main()
{
const_lock<std::vector<int>> v;
v.push_back(5);
v.push_back(7);
if (rand() % 2)
v.set_const_lock(true);
v.push_back(9); // fails compilation
std::cout << v.at(1) << std::endl; // ok
}
You need to completely rethink your approach. 您需要完全重新考虑您的方法。
Below is an example illustrating what I would be trying to protect against 下面是一个示例,说明了我将要防范的内容
class Node
{
public:
Node(int id) : my_id(id) {}
// . . .
int id() {return my_id;}
private:
int my_id;
// . . .
};
class Grid
{
public:
Grid() {}
// . . .
void associate(Node* n) { my_nodes.push_back(n); }
private:
// . . .
std::vector<Node*> my_nodes;
};
Node* find(std::vector<Node>& Nodes, int ID)
{
for(auto i=Nodes.begin(); i!=Nodes.end(); ++i)
{
if (i->id() == ID)
{
return &*i;
}
}
}
main()
{
std::vector<Node> Nodes;
// fill Nodes with data
Grid Array;
Array.associate( find(Nodes,14325) );
Array.associate( find(Nodes,51384) );
Array.associate( find(Nodes,321684) );
// . . .
Nodes.push_back(Node(21616)); // this can invalidate my pointers in Array
}
If I was able to make my Nodes vairable be 如果我能够使我的节点可变
const_lock<std::vector<Node>> Nodes;
then call 然后打电话
Nodes.set_const_lock(true);
after populating the data, I wouldn't need to worry about my pointers in Array getting messed up. 填充数据后,无需担心Array中的指针弄乱了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.