C++ 在C+中假装静态+;
我正在测试各种优化的组合,对于这些,我需要一个静态if,如中所述,以启用和禁用特定优化。if(const expr)并不总是有效,因为某些优化涉及更改数据布局,而这不能在函数范围内完成 基本上我想要的是:C++ 在C+中假装静态+;,c++,optimization,if-statement,static,static-if,C++,Optimization,If Statement,Static,Static If,我正在测试各种优化的组合,对于这些,我需要一个静态if,如中所述,以启用和禁用特定优化。if(const expr)并不总是有效,因为某些优化涉及更改数据布局,而这不能在函数范围内完成 基本上我想要的是: template<bool enable_optimization> class Algo{ struct Foo{ int a; if(enable_optimization){ int b; } void bar(){
template<bool enable_optimization>
class Algo{
struct Foo{
int a;
if(enable_optimization){
int b;
}
void bar(){
if(enable_optimization){
b = 0;
}
}
};
};
文件c.h
template<>
class Algo<ENABLE_OPTIMIZATION>{
struct Foo{
int a;
#if ENABLE_OPTIMIZATION
int b;
#endif
void bar(){
#if ENABLE_OPTIMIZATION
b = 0;
#endif
}
};
};
模板
类算法{
结构Foo{
INTA;
#如果启用"优化",
int b;
#恩迪夫
空条(){
#如果启用"优化",
b=0;
#恩迪夫
}
};
};
有人知道更好的方法吗?理论上,它可以通过使用模板元编程来完成,首先我使用了它。至少我使用它的方式是一种痛苦,导致完全无法阅读和臃肿的代码。使用上面的黑客可以显著提高生产率
编辑:我有几个优化标志,它们相互作用。没有理由使用模板使代码变得更复杂:
template<bool enable_optimization>
class FooOptimized
{
protected:
int b;
void bar_optim()
{
b = 0;
}
};
template<>
class FooOptimized<false>
{
protected:
void bar_optim() { }
};
template<bool enable_optimization>
struct Algo
{
struct Foo : FooOptimized<enable_optimization>
{
int a;
void bar()
{
this->bar_optim();
}
};
};
您必须对其进行分析和测试,以确定虚拟函数的开销是否比不依赖于模板参数的
Algo
和Algo::Foo
中的代码复制要小。注意:目前,这种方法不起作用,因为如果不为一个类中的某个成员分配空间,似乎就无法在该类中拥有该成员。如果您对如何使其工作有想法,请随意编辑。
你可以用这样一个成语:
template<bool optimized, typename T> struct dbg_obj {
struct type {
// dummy operations so your code will compile using this type instead of T
template<typename U> type& operator=(const U&) { return *this; }
operator T&() { return *static_cast<T*>(0); /* this should never be executed! */ }
};
};
template<typename T> struct dbg_obj<false, T> {
typedef T type;
};
template<bool enable_optimization>
class Algo{
struct Foo{
int a;
typename dbg_obj<enable_optimization, int>::type b;
void bar(){
if(enable_optimization){
b = 0;
}
}
};
};
模板结构dbg_obj{
结构类型{
//伪操作,因此您的代码将使用此类型而不是T编译
模板类型&运算符=(常量U&){return*this;}
运算符T&({return*static_cast(0);/*永远不应执行此操作!*/}
};
};
模板结构dbg_obj{
T型;
};
模板
类算法{
结构Foo{
INTA;
类型名称dbg_obj::类型b;
空条(){
如果(启用_优化){
b=0;
}
}
};
};
如果禁用优化,这将为您提供一个正常的int
成员。如果启用了优化,则b
的类型是没有成员的结构,不会占用任何空间
由于您的方法
bar
使用运行时if
来决定是否访问b
,与模板专门化等明确的编译时机制相反,您在b
上使用的所有操作也必须从虚拟结构中可用。即使相关的部分永远不会被执行,并且编译器很可能会对它们进行优化,正确性检查也是第一位的。因此,必须为替换类型编译行b=0
。这就是虚拟赋值和虚拟强制转换操作的原因。尽管这两种方法都可以满足您的代码,但我将它们都包括在内,以防它们在其他方面被证明有用,并让您了解如何在需要它们时添加更多内容。Jonathan Wakely提出的静态解决方案(而非动态解决方案)是一条可行之路
想法很简单:
是具体的数据b
- 有一个涉及它的单一操作(包括设置它的值)
template <typename T> struct FooDependent;
template <>
struct FooDependent<true> {
int b;
void set(int x) { b = x; }
};
template <>
struct FooDependent<false> {
void set(int) {}
};
注意:在模板化代码中使用
此
来访问基类成员,否则好的编译器将拒绝您的代码。预处理器开关听起来不像是一个糟糕的黑客。@zneak,这取决于条件编译对代码的影响程度,如果预处理器启用/禁用了大量块,bar
的实现可能会变得更难阅读和理解。将它分成优化的和非优化的部分可能会更简单,但是很难知道,因为一个极小的例子没有显示真正的代码是什么。下一个C++标准将有STATICIIIF?@?.AuBuIS,没有人知道,但是没有什么被接受或决定。请注意,<代码>如果CONTXPRPR < /代码>(以前称为static if
)现在很可能是C++17的一部分。我想你没有注意到他根本不希望b在优化版本中存在,而不仅仅是初始化-他说的是“更小的内存占用”@gbjbaanb,我想你没有注意到,b
存在于OP的优化版本中,而不是在未优化的版本中,并且在我的版本中也是一样的,不是吗?但是……如何向每个对象添加虚拟指针(至少使每个类实例的大小增加一倍)实现更小的内存占用目标?如果你想取消运行时技巧,那么它将成为一个更好的答案。@MatthieuM。答案的前半部分解决了OP的确切问题,后半部分显示了一个可能有用的替代方案-当你不知道实际co的大小时,你不知道它会使类的大小加倍de(我假设OP的真实代码没有将int设置为零,这可能有点复杂!)我在回答的后半部分的观点是如果“优化”目标是,复制代码可能会导致比使用虚拟函数更差的性能,并且可能会比添加vtable更大地增加可执行文件的大小。就我个人而言,我不认为这种预处理器条件很容易解释,而是将算法分成正交的部分,捕获独立的变化(正如Alexandrescu的现代C++设计)肯定不是TIVI
struct FooImpl
{
virtual void bar() { }
};
class FooOptimized : FooImpl
{
int b;
void bar()
{
b = 0;
}
};
struct Algo
{
class Foo
{
std::unique_ptr<FooImpl> impl;
public:
explicit
Foo(bool optimize)
: impl(optimize ? new FooOptimized : new FooImpl)
{ }
int a;
void bar()
{
impl->bar();
}
};
};
template<bool optimized, typename T> struct dbg_obj {
struct type {
// dummy operations so your code will compile using this type instead of T
template<typename U> type& operator=(const U&) { return *this; }
operator T&() { return *static_cast<T*>(0); /* this should never be executed! */ }
};
};
template<typename T> struct dbg_obj<false, T> {
typedef T type;
};
template<bool enable_optimization>
class Algo{
struct Foo{
int a;
typename dbg_obj<enable_optimization, int>::type b;
void bar(){
if(enable_optimization){
b = 0;
}
}
};
};
template <typename T> struct FooDependent;
template <>
struct FooDependent<true> {
int b;
void set(int x) { b = x; }
};
template <>
struct FooDependent<false> {
void set(int) {}
};
struct Foo: FooDependent<enable_optimization> {
int a;
void bar() { this->set(0); }
};