我正在尝试运行以下C++代码:
#include <cmath>
template<typename T, bool> class ConditionalData {
};
template <typename T> class ConditionalData<T, false> {
};
template <typename T> class ConditionalData<T, true> {
private:
T data;
public:
void setData(T _data) { data = _data; }
};
template<bool hasdata> class A {
public:
A() {
ConditionalData<double,hasdata> data;
if (hasdata) {
data.setData(sin(cos(123.4)));
}
}
};
int main(int argNum, const char**argData) {
A<false> test1;
A<true> test2;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
本质上,我想实现一个模板化的类A,其中根据模板参数执行某些操作.这些操作需要局部变量,我只想在需要时分配它们.我在这里遇到的问题是身体的问题
if (hasdata) {
data.setData(3);
}
Run Code Online (Sandbox Code Playgroud)
条件也是为hasdata = false实例化的,它不能编译(使用g ++ 5.2).任何想法如何以最干净的方式完成这项工作而不将A :: A()的主体分成几部分?
上面的源代码是一个最小的非工作示例.A :: A()的实际实现相对较长,依赖于"hasdata"的部分均匀分布在代码上.此外,将使用类A的"typename T"是具有重量级构造函数/析构函数的相对复杂的类,因此我希望仅在hasdata = true时分配T的实例.最后,在data.setData(...)调用中,"..."中可能存在复杂的计算,只有在需要时才应执行.
Pio*_*cki 13
如果你能负担得起c ++ 14,你可以将条件分支表示为通用lambdas.好处是它们捕获周围的变量,解决方案不需要额外的成员函数.
template <bool> struct tag {};
template <typename T, typename F>
auto static_if(tag<true>, T t, F f) { return t; }
template <typename T, typename F>
auto static_if(tag<false>, T t, F f) { return f; }
template <bool B, typename T, typename F>
auto static_if(T t, F f) { return static_if(tag<B>{}, t, f); }
template <bool B, typename T>
auto static_if(T t) { return static_if(tag<B>{}, t, [](auto&&...){}); }
// ...
ConditionalData<int, hasdata> data;
static_if<hasdata>([&](auto& d)
{
d.setData(3);
})(data);
Run Code Online (Sandbox Code Playgroud)
在c ++ 17中你可以说:
if constexpr (hasdata)
{
data.setData(3);
}
Run Code Online (Sandbox Code Playgroud)
这是一种常见的模式,因此实际上有一篇文章要添加constexpr_if到C++中.如果它适用于未来版本,它将允许您保持代码非常原样.
template<bool hasdata> class A {
public:
A() {
ConditionalData<int,hasdata> data;
constexpr_if (hasdata) {
//^^^^^^^^^^ instead of plain if
data.setData(3);
}
}
};
Run Code Online (Sandbox Code Playgroud)
目前,您需要处理其他一个答案.
编辑:这被添加到C++ 17并被调用 if constexpr
首先,您不需要3个版本class ConditionalData,因为bool可以是true或者false.所以让我简化如下:
template<typename T, bool = false> class ConditionalData {
}; //^^^^^^^^^^^^
template <typename T> class ConditionalData<T, true> {
private:
T data;
public:
void setData(T _data) { data = _data; }
};
Run Code Online (Sandbox Code Playgroud)
其次,回答你的问题:无论哪个成员属于false类别,只需将它们超出class身体,如下所示:
template<bool hasdata> class A {
public:
A() {
ConditionalData<int,hasdata> data;
if (hasdata) {
data.setData(3);
}
}
};
template<> A<false>::A() {} // Does nothing for `false` condition
Run Code Online (Sandbox Code Playgroud)