用std::function初始化匿名class成员变量
Initialization of anonymous class member variable with std::function
不知道有没有办法解决这种情况:
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
-这很糟糕,因为这需要源文件,这需要创建这样的文件,这需要一些努力和破坏我美丽的 header-only class 层次结构! (我的意思是,我可以偷懒并在 header 中定义此变量,但随后会出现多重定义问题)。我知道这可能是一个糟糕的设计(我只是在测试),但是你知道如何在不涉及源文件的情况下解决这个问题吗?
我觉得我在某种程度上颠覆了你的意图,但如果你在构造函数中初始化变量,你可以使事情正常进行。
#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;
}
尽管您的示例是人为设计的,但有时我需要(或更方便地)以类似方式初始化复杂对象。
但是,为什么要使用 std::function<>?为什么不直接使用函数?
class A
{
class
{
public:
void setValue(int val) { i = val; }
private:
int i;
} B = initB(10);
static decltype(B) initB(int value)
{
decltype(B) temp;
temp.setValue(value);
return temp;
}
};
虽然,我通常不会使用 decltype(B);我只想给 class 起个名字。
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;
}
不知道有没有办法解决这种情况:
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
-这很糟糕,因为这需要源文件,这需要创建这样的文件,这需要一些努力和破坏我美丽的 header-only class 层次结构! (我的意思是,我可以偷懒并在 header 中定义此变量,但随后会出现多重定义问题)。我知道这可能是一个糟糕的设计(我只是在测试),但是你知道如何在不涉及源文件的情况下解决这个问题吗?
我觉得我在某种程度上颠覆了你的意图,但如果你在构造函数中初始化变量,你可以使事情正常进行。
#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;
}
尽管您的示例是人为设计的,但有时我需要(或更方便地)以类似方式初始化复杂对象。
但是,为什么要使用 std::function<>?为什么不直接使用函数?
class A
{
class
{
public:
void setValue(int val) { i = val; }
private:
int i;
} B = initB(10);
static decltype(B) initB(int value)
{
decltype(B) temp;
temp.setValue(value);
return temp;
}
};
虽然,我通常不会使用 decltype(B);我只想给 class 起个名字。
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;
}