我想创建一个允许我锁定对象被修改的类。它本质上是一个模板,带有一个指定锁定状态的布尔值。由于它是一个模板,我不会知道可以在内部对象上调用的所有方法,所以我需要一个方法来传递调用...
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
}
任何帮助将不胜感激。谢谢!
编辑:将静态断言更改为throw和exception
答案 0 :(得分:2)
您尝试做的事情看起来相当困难,但更重要的是,过度复杂并且不必为您所做的事情做好准备。
基本上你正在尝试做的事情(如果我错了,请纠正我)是创建一个编译时检查你是否应该能够在给定时间修改一个对象。但是,c ++已经有了内置的方法。只需声明或传递您的对象为const或const&amp;,编译器将不允许您修改对象的不可变部分。当你想要能够修改它时,不用const就传递它。你甚至可以从const&amp; amp;常规&amp;当你想从代码中去,你可以直接将代码修改为代码,尽管我不推荐它。
编辑:刚看到关于没有参考数组的问题的评论。别担心!标准库支持引用包装器,它允许您基本上将引用存储在数组或其他任何地方。
答案 1 :(得分:1)
您可以创建一个通用的包装类,您可以将该函数转发到使用lambda来捕获对内部成员的引用。在这个例子中,我只是使用if语句来检查它是否被锁定&#34;如果是,那么我们只需修改副本。
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;
});
}
答案 2 :(得分:0)
这完全无法实现。对源代码进行了一些简单的修改,说明了为什么这不起作用。
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
}
你需要彻底重新思考你的方法。
答案 3 :(得分:0)
下面是一个示例,说明了我要保护的内容
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
}
如果我能够使我的节点变得可以
const_lock<std::vector<Node>> Nodes;
然后致电
Nodes.set_const_lock(true);
填充数据后,我不需要担心我的数组中的指针搞砸了。