【发布时间】:2020-12-07 17:06:40
【问题描述】:
我创建了这个类,因此我可以拥有任何类型的值,该值可以是固定的,也可以在每次使用时重新计算:
template<typename T>
class Value {
private:
bool fixed;
union {
T value;
std::function<T()> get;
};
public:
Value(const T& value) : fixed(true), value(value) {}
Value(const std::function<T()>& get) : fixed(false), get(get) {}
Value(const T *pointer) : Value([pointer]() { return *pointer; }) {}
~Value() {}
operator T() { return fixed ? value : get(); }
};
以下所有表达式似乎都可以正常工作:
Value<double> a = 2.2;
double b = 1.;
double c = a;
Value<double> d = &b;
Value<int> e = Value<int>([]() { return 1.; });
但是当我尝试这样做时:
Value<double> f = []() { return 1.; };
触发编译错误:
error: conversion from 'main()::<lambda()>' to non-scalar type 'Value<double>' requested
你可以试试这个例子here。
为什么分配适用于T 而不是std::function<T()>,我怎样才能做到这一点?
注意:我知道this answer,但我不清楚如何解决这个问题,而不必像为Value<double> e 那样显式调用构造函数。
【问题讨论】:
-
@SilvioMayolo 刚刚添加了一个指向我正在测试的平台的链接。
-
在你的godbolt链接中,这行写着
Value<int> e = Value<int>([]() { return 1; });,而这里的Value<double> e = Value<int>([]() { return 1.; });是一个错误 -
@largest_prime_is_463035818 应该修复。我将所有内容都转换为双精度以简化问题,但忘记在 Godbolt 上进行更改。
-
你可以写
auto f = Value<int>([]() { return 1; });如果你担心把类型拼写两次。它基本相同,并且有效;) -
我建议用
std::variant替换这个类的内部结构。此外,对于前两个构造函数,由于Value想要“获得”(即保存)参数,您应该按值(无引用限定符)和std::move将参数设置为数据成员。这样,调用者可以控制是复制还是移动,而不是强制复制。
标签: c++ templates lambda std-function