c++ - 让类继承模板类型的构造函数
问题描述
我创建了以下类来创建任何类型的值,这些值在每次使用调用运算符时都是固定的或重新计算的:
template <typename T>
class DynamicValue {
private:
std::variant<T, std::function<T()>> getter;
public:
DynamicValue(const T& constant) : getter(constant){};
template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
DynamicValue(F&& function) : getter(function) {}
DynamicValue(const T* pointer) : DynamicValue([pointer]() { return *pointer; }) {}
DynamicValue(const DynamicValue& value) : getter(value.getter) {}
~DynamicValue() {}
DynamicValue& operator=(const DynamicValue& value) {
getter = value.getter;
return *this;
}
T operator()() {
return getter.index() == 0 ? std::get<T>(getter) : std::get<std::function<T()>>(getter)();
}
};
我还编写了以下虚拟结构来展示我的问题:
struct A {
int b;
};
问题是,理想情况下,我可以初始化 any DynamicValue<T>
,就好像它是 type 一样T
。所以,在这个例子中,因为我可以做A a = {1};
,而不是必须写DynamicValue<A> a = A{1};
,我可以做DynamicValue<A> a = {1};
。但是,当我尝试这样做时,出现以下错误:
无法将“{1}”从“”转换为“DynamicValue”
你可以在这里尝试一个活生生的例子。
无论如何要克服这个问题还是我必须接受更长的语法?
解决方案
您可以添加一个构造函数,该构造函数接受类型所需的所有参数T
并将它们转发给构造函数T
并初始化您的内部值getter
。
只需将以下行添加到您的类中:
template < typename ... S> DynamicValue( S&& ... parms ): getter{T{ std::forward<S...>( parms... )}} {}
但!如果我们这样做,如果我们传递一个非 const DynamicValue,它也会被调用。所以我们必须通过 SFINAE 排除它并得到:
template <typename F,
typename = std::enable_if_t<std::is_invocable_v<F>&& !std::is_same_v<std::remove_reference_t<F>, DynamicValue<T>>, bool>>
DynamicValue(F&& function) : getter(function) {}
但是还有一个问题:
您的代码已经有一些东西可以作为不想要的复制构造函数调用!
构造函数:
template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
DynamicValue(F&& function) : getter(function) {}
也将被调用,因为也是可调用的DynamicType<T>
!我们还必须使用第二个条件来禁用类型的实例化,DynamicType<T>
这会导致:
template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>&& !std::is_same_v<std::remove_reference_t<F>, DynamicValue<T>>, bool>>
DynamicValue(F&& function) : getter(function) {}
您可以创建一个实例:
DynamicValue<A> a1 = A{1};
DynamicValue<A> a2{1};
使用= {1}
将不起作用。
现在甚至片段
DynamicValue<A> a9{100};
DynamicValue<A> a10(a9);
std::cout << a10().b << std::endl;
按预期工作。
推荐阅读
- web-scraping - 所有亚马逊产品的大规模价格跟踪架构
- javascript - v-card backgroundColor 没有使用 getElementById 改变
- powershell - 通过命令行在没有提示的情况下安装 VpnClientSetupAmd64.exe
- python - 我需要帮助限制 groupby 以返回特定范围内的值并在折线图上绘制每年的平均值
- prolog - 如何从术语中获取简单元素?
- oracle - Oracle UTL_TCP 到 Graylog GELF TCP 错误 - GELF 消息太短。甚至类型标题都不适合
- regex - 如何仅过滤其所有字段都满足正则表达式条件的行
- excel - 从 Word 到 Excel 的 VBA SQL 连接不返回任何记录
- javascript - 我有一个对象数组,每个对象都有一个“user_id”键,我需要在 Rethinkdb 中从这个用户那里获取更多信息
- node.js - 我得到 - “TypeError:客户端在 Client.query 中传递了一个空或未定义的查询”,即使我的代码中没有空或未定义的查询