我想知道是否有解决方法就是这样的情况:
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = initB(10);
std::function<decltype(B)(int)> initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
}
//...
A a; //crash
//...
我想这是由初始化顺序引起的。通过调用未经授权的B
实例来启动变量std::function
,从而导致崩溃。根据我的逻辑,解决方法是首先初始化std::function
,然后初始化成员B
。但是,这样的代码无效:
class A
{
//error: 'B' was not declared in this scope
std::function<decltype(B)(int)> initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = initB(10);
}
我尝试制作std::function
static
,这样的代码有效,但需要non-constexpr/const
成员,因为std :: function有non-trivial destructor
- 这很糟糕,因为这需要源文件,这需要创建这样的文件,这需要一些efford和破坏我美丽的标题类层次结构! (我的意思是,我可能很懒,并在标题中定义此变量,但随后出现多重定义问题)。我知道这可能是一个糟糕的设计(我只是测试一下),但你有没有想法如何解决问题而不涉及源文件?
答案 0 :(得分:1)
尽管你的例子是人为的,但有时我需要(或更方便)以类似的方式初始化复杂对象。
但是,为什么要使用std :: function&lt;&gt;?为什么不直接使用函数?
findLimit(new_starting_limit);
虽然,我通常不会使用decltype(B);我会给这个班级一个名字。
答案 1 :(得分:0)
我觉得我在某种程度上颠覆了你的意图,但是如果你在构造函数中初始化变量,你就可以使事情有效。
#include <functional>
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B;
std::function<decltype(B)(int)> initB;
public:
A() {
initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
B = initB(10);
}
};
int main() {
A a;
}
答案 2 :(得分:0)
A :: initB是一个值。它没有在您调用它时初始化,因为初始化是按照您指定成员字段的顺序(松散地说)完成的。您可以通过执行以下操作来验证这一点,该工作正常:
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename U>
T set(T& tgt, const U& src)
{
new(&tgt) T(src);
return tgt;
}
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = set(initB, [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;})(10);
std::function<decltype(B)(int)> initB;
};
int main() {
A a;
}