我有一个看起来像这样的构造函数:
SomeType(const bool condition = true) {
if (condition) {
// do some init
} else {
// do some other init
}
}
但是由于condition
在编译时是已知的,我怀疑这可以改进,避免传递变量并在运行时评估if语句。这是真的?怎么可能呢?
答案 0 :(得分:3)
C ++中没有语法来调用像
这样的简单模板化构造函数struct SomeType
{
template <bool condition>
SomeType();
};
template<>
SomeType::SomeType<true>()
{
// do some init
}
template<>
SomeType::SomeType<false>()
{
// do some other init
}
// ...
SomeType<true> st; // this syntax is used to create an object of a class template:
// template <bool>
// struct SomeType
// {
// };
一个众所周知的解决方法是通过函数重载来模仿模板特化:
#include <type_traits>
struct SomeType
{
SomeType(std::true_type)
{
// do some init
}
SomeType(std::false_type)
{
// do some other init
}
template <bool condition>
static SomeType New()
{
return SomeType(std::integral_constant<bool, condition>{});
}
};
使用示例:
auto st = SomeType::New<false>();
在此代码中,使用了来自std::integral_constant
标头的C ++ 11 type_traits
模板类,但它足以在C ++ 03中编写类似的类模板。
答案 1 :(得分:1)
如果条件始终是编译时常量,则可以这样做 类似的东西:
class SomeType
{
void initTrue() {}
void initFalse() {}
public:
template <bool C>
struct Discrim {}
SomeType( Discrim<true> ) { initTrue(); }
SomeType( Discrim<false> ) { initFalse(); }
};
然后你必须用:
调用它SomeType((SomeType::Discrim<condition>()));
或者您可以简单地定义两个枚举,您可以在其上 重载构造函数:
class SomeType
{
void initTrue() {}
void initFalse() {}
public:
enum ConditionTrue { conditionTrue };
enum ConditionFalse { conditionFalse };
SomeType( ConditionTrue ) { initTrue(); }
SomeType( ConditionFalse ) { initFalse(); }
};
或者你可以做你正在做的事情;它不太可能
额外的测试将为运行时间增加一个可测量的差异。
如果它(如分析器所示),它只能是那样
构造函数小到可以内联(在这种情况下,
优化器中的常量传播将确保存在
没有实际的if
)。上述技术通常仅有用
当你想要具有明显的独立构造函数时
不同的初始化列表。
答案 2 :(得分:0)
如果您不信任编译器,那么您(也许)可以将您的类的构造函数作为模板:
template< bool condition >
SomeType();
template<>
SomeType< true >() {
// do some init
}
template<>
SomeType< false >() {
// do some other init
}
修改强> 正如@Constructor(名字所说的那样))))说你不能调用这种类型的构造函数。因此,您可以在函数中移动所有初始化。像这样:
struct SomeType {
template< bool condition >
void init();
};
template<>
void SomeType::init< true >() {
// do some init
}
template<>
void SomeType::init< false >() {
// do some other init
}
SomeType t;
t.init< true >();
SomeType f;
f.init< false >();