C++ 转换构造函数的隐式参数
tl;Dr:<强>有没有方法将当前范围中的默认参数添加到C++中的所有隐式构造函数? 我目前正在设计一个C++语言的嵌入式接口。目标是使语法正确的表达式的创建既安全又方便。现在,我认为学习像boost::proto这样的重量级实现会给开发带来太大的延迟,所以我尝试推出自己的实现 下面是一个小演示:C++ 转换构造函数的隐式参数,c++,implicit-conversion,implicit,default-arguments,dynamic-scope,C++,Implicit Conversion,Implicit,Default Arguments,Dynamic Scope,tl;Dr:有没有方法将当前范围中的默认参数添加到C++中的所有隐式构造函数? 我目前正在设计一个C++语言的嵌入式接口。目标是使语法正确的表达式的创建既安全又方便。现在,我认为学习像boost::proto这样的重量级实现会给开发带来太大的延迟,所以我尝试推出自己的实现 下面是一个小演示: #include <iostream> #include <string> #include <sstream> class ExprBuilder { public:
#include <iostream>
#include <string>
#include <sstream>
class ExprBuilder
{
public:
ExprBuilder(const int val) : val(std::to_string(val)) {}
ExprBuilder(const std::string val) : val(val) {}
ExprBuilder(const char* val) : val(val) {}
ExprBuilder(const ExprBuilder& lhs, const ExprBuilder& arg) {
std::stringstream ss;
ss << "(" << lhs.val << " " << arg.val << ")";
val = ss.str();
}
const ExprBuilder operator()(const ExprBuilder& l) const {
return ExprBuilder(*this, l);
}
template<typename... Args>
const ExprBuilder operator()(const ExprBuilder& arg, Args... args) const
{
return (*this)(arg)(args...) ;
}
std::string val;
};
std::ostream& operator<<(std::ostream& os, const ExprBuilder& e)
{
os << e.val;
return os;
}
int main() {
ExprBuilder f("f");
std::cout << f(23, "foo", "baz") << std::endl;
}
#包括
#包括
#包括
类ExprBuilder
{
公众:
ExprBuilder(const int val):val(std::to_string(val)){}
ExprBuilder(const std::string val):val(val){}
ExprBuilder(const char*val):val(val){}
ExprBuilder(const ExprBuilder&lhs、const ExprBuilder&arg){
std::stringstream-ss;
ss如果没有全局/静态变量,这几乎是不可能的,因为如果没有全局/静态信息,局部变量Owner-Owner
和ExprBuilder f
就无法相互了解
我认为最干净的方法是添加一个
static Owner* current_owner;
到ExprBuilder
类。然后您可以添加一个新类ScopedCurrentOwnerLock
,该类在构造函数中设置当前所有者,并在析构函数中将其设置为nullptr。然后您可以使用它,类似于互斥锁:
class ScopedCurrentOwnerLock {
public:
ScopedCurrentOwnerLock(Owner const& owner) {
ExprBuilder::current_owner = &owner;
}
~ScopedCurrentOwnerLock() {
ExprBuilder::current_owner = nullptr;
}
};
int main() {
Owner owner;
ScopedCurrentOwnerLock lock(owner);
ExprBuilder f("f");
}
如果您有权访问所有者
代码,则可以省略ScopedCurrentOwnerLock
类,直接在所有者
的构造函数/析构函数中设置/取消设置指针
请注意此解决方案存在以下两个问题:
- 如果所有者在锁超出范围之前超出范围,则指针无效
- 如果同时有多个锁,静态指针的行为是不可预测的,例如由于多线程
您所有的exprbuilder
都依赖于所有者
,您当然不需要全局状态。因此您必须将所有者传递给每个构造函数
如果您确实不想将所有者添加到块中的所有实例化中,
,您可以创建一个工厂来为您传递它
struct ExprBuilderFactory
{
Owner & owner;
ExprBuilder operator()(int val) { return ExprBuilder(owner, val); }
ExprBuilder operator()(char * val) { return ExprBuilder(owner, val); }
// etc
}
int main() {
Owner owner;
ExprBuilderFactory factory{ owner };
ExprBuilder f = factory("f");
}
我认为您所说的是某种全局变量
您可以使用Owner
Raii设置一个静态/全局变量,并在ExprBuilder
中使用该全局变量。您的意思是使用唯一的\u ptr作为全局变量,以确保它仅在上下文中使用,并且必须显式保留吗如果用户忘记了指针,则不会产生运行时错误?@appleapple OP已经说过“我不想在这里使用静态字段”。静态成员变量是全局变量的一种特殊类型。我强烈怀疑他的反对意见会适用于任何其他类型。@choeger:我想你有一个全局变量(如果这是遗留代码,则可能是指向某个对象的指针),然后是一个RAII类,用于设置该全局变量并随后取消设置。
struct ExprBuilderFactory
{
Owner & owner;
ExprBuilder operator()(int val) { return ExprBuilder(owner, val); }
ExprBuilder operator()(char * val) { return ExprBuilder(owner, val); }
// etc
}
int main() {
Owner owner;
ExprBuilderFactory factory{ owner };
ExprBuilder f = factory("f");
}