Mir*_*pas 3 c++ template-function c++11 static-if
我希望能够避免在条件为false时调用函数,这在编译时已知.现在我使用这样的东西:
template<bool Enabled>
void fun(params)
{
//do nothing
}
template<>
void fun<true>(params)
{
//do something with params.
}
Run Code Online (Sandbox Code Playgroud)
params即使函数体是空的,我也不喜欢这种方法.
我想要一个解决方案,当根本没有调用该函数时,当条件为假时,不会对params进行求值(这可能在第一种情况下使用空函数进行优化,但我不能认为这是真的.编译器).
这甚至可能吗?
Yak*_*ont 13
是的.
template<bool b, typename Func, typename FuncElse>
struct compile_time_if_functor {
void operator()( Func&& f, FuncElse&& ) const{
std::forward<Func>(f)();
}
};
template<typename Func, typename FuncElse>
struct compile_time_if_functor<false, Func, FuncElse> {
void operator()( Func&&, FuncElse&& else_f ) const{
std:forward<FuncElse>(else_f)();
}
};
template<bool b, typename Func, typename Else>
void compile_time_if( Func&& f, Else&& elsef ) {
compile_time_if_functor<b, Func, Else> functor;
functor(
std::forward<Func>(f),
std::forward<Else>(elsef)
);
}
template<bool b, typename Func>
void compile_time_if( Func&& f ) {
auto do_nothing = []{};
compile_time_if<b>( std::forward<Func>(f), std::move(do_nothing) );
}
Run Code Online (Sandbox Code Playgroud)
使用:
int main() {
compile_time_if<expression>([&]{
// code that runs iff expression is true
});
compile_time_if<expression2>([&]{
// code that runs iff expression2 is true
},[&]{
// else clause, runs iff expression2 is false
});
}
Run Code Online (Sandbox Code Playgroud)
请注意,里面的代码{}是编译的,但是如果它在错误的分支中则不会运行if.因此,代码需要在类型级别上形成良好且合法,但在运行时执行并不一定合法.在这些lambda中没有创建大小为0的数组!
更高级的方法可以让你无限制地链接if-else块.如果我想这样做,我会使用命名运算符技巧.
首先,改变compile_time_if回归std::integral_constant< bool, b >.
然后,写入compile_time_else(Func&&)和compile_time_elseif<bool>(Func&&)返回类型打包Func和覆盖,operator*( std::true_type, X )以及operator*( std::false_type, X )运行或不运行Func和返回std::true_type或std::false_type.
最终目标是这种语法:
If<expression>([&]{
// block 1
})*Else([&]{
// block 2
});
If<expression>([&]{
// block 1
})*ElseIf<expression2>([&]{
// block 2
})*ElseIf<expression3>([&]{
// block 3
})*Else([&]{
// block 4
});
Run Code Online (Sandbox Code Playgroud)
允许全程级联流量控制.你甚至可以做到:
compile_time_switch<value>(
Case<c0, FallThrough>(),
Case<c1>([&]{
// block 1
}),
Case<c2, Continue>([&]{
// block 2
}),
Case<c3>([&]{
// block 3
}),
Case<c4>([&]->CanContinue{
// block 4
if (condition) {
return Continue;
} else {
return Break;
}
}),
Case<c4>([&]{
}),
Default([&]{
})
};
Run Code Online (Sandbox Code Playgroud)
但那是领先于我们自己.
有关如何以允许编译器在编译时操作流控制的方式来复制C++语法的想法,请查看boost phoenix.我只是把它包含在这里是为了完整性:实际上写这种东西并不是那么实用,因为一些可怜的草皮将不得不维护它,并且你最初几次写这些东西你将会做一份糟糕的工作!