是的。
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));
}
使用:
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
});
}
注意,{}
内的代码被编译,但不运行,如果是在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
});
使全级联上的流量控制。你甚至可以这么做:
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([&]{
})
};
但那是超越自我。
有关如何以编译时允许编译器操作流控制的方式复制C++语法的想法,请查看boost phoenix。我只是为了完整而将其包括在内:实际上写这种东西并不是那么实际,因为一些可怜的草皮将不得不维持它,并且在你写这些东西的前几次你会做一份糟糕的工作!
你确定编译器没有这样做吗? – 2013-04-27 20:50:12
@BoPersson如果参数评估有副作用,即使函数体是空的,也应该评估它们。在标准AFAIK中也没有规定,如果空函数是空的,则不应调用空函数(这可能由大多数编译器完成) – Felics 2013-04-27 20:56:09
我相信你回答了你自己的问题。 – jrok 2013-04-27 20:58:33