在对象中传递函数和运算符调用
Passing function and operator calls in object
我想制作一个 class,它允许我锁定对象以防止被修改。它本质上是一个带有指定锁定状态的布尔值的模板。由于是模板,我不会知道所有可以在内部对象上调用的方法,所以我需要一个方法来传递调用...
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
}
如有任何帮助,我们将不胜感激。谢谢!
编辑:将静态断言更改为抛出和异常
您尝试做的事情看起来相当困难,但更重要的是,对于您尝试做的事情来说过于复杂且不必要。
本质上,您要做的(如果我错了请纠正我)是创建一个编译时检查,检查您是否应该能够在给定时间修改对象。然而,c++ 已经有一个内置的方法来做到这一点。只需将您的对象声明或传递为 const 或 const&,编译器将不允许您修改对象的非可变部分。当您希望能够修改它时,请在不使用 const 的情况下传递它。您甚至可以将它从 const& 转换为常规 & 当您想从无法直接修改它的代码转到可以直接修改的代码时,尽管我不推荐这样做。
编辑:刚刚看到关于无引用数组问题的评论。别担心!标准库支持引用包装器,它允许您实质上将引用存储在数组或其他任何地方。
您可以创建一个通用包装器 class,您可以将函数转发给使用捕获对内部成员的引用的 lambda。在这个例子中,我只是使用一个 if 语句来检查它是否是 "locked",如果是,那么我们只修改一个副本。
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;
});
}
这是完全无法实现的。对您的源代码进行微不足道的修改即可说明为什么这行不通。
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
}
您需要彻底重新考虑您的方法。
下面是一个示例,说明了我要尝试防范的内容
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);
填充数据后,我不必担心数组中的指针会弄乱。
我想制作一个 class,它允许我锁定对象以防止被修改。它本质上是一个带有指定锁定状态的布尔值的模板。由于是模板,我不会知道所有可以在内部对象上调用的方法,所以我需要一个方法来传递调用...
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
}
如有任何帮助,我们将不胜感激。谢谢!
编辑:将静态断言更改为抛出和异常
您尝试做的事情看起来相当困难,但更重要的是,对于您尝试做的事情来说过于复杂且不必要。
本质上,您要做的(如果我错了请纠正我)是创建一个编译时检查,检查您是否应该能够在给定时间修改对象。然而,c++ 已经有一个内置的方法来做到这一点。只需将您的对象声明或传递为 const 或 const&,编译器将不允许您修改对象的非可变部分。当您希望能够修改它时,请在不使用 const 的情况下传递它。您甚至可以将它从 const& 转换为常规 & 当您想从无法直接修改它的代码转到可以直接修改的代码时,尽管我不推荐这样做。
编辑:刚刚看到关于无引用数组问题的评论。别担心!标准库支持引用包装器,它允许您实质上将引用存储在数组或其他任何地方。
您可以创建一个通用包装器 class,您可以将函数转发给使用捕获对内部成员的引用的 lambda。在这个例子中,我只是使用一个 if 语句来检查它是否是 "locked",如果是,那么我们只修改一个副本。
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;
});
}
这是完全无法实现的。对您的源代码进行微不足道的修改即可说明为什么这行不通。
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
}
您需要彻底重新考虑您的方法。
下面是一个示例,说明了我要尝试防范的内容
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);
填充数据后,我不必担心数组中的指针会弄乱。