在混合运行时/编译时条件下调度标记
Tag dispatching on mixed runtime/compile time condition
我有以下标签调度代码(参见LiveWorkSpace)
#include <iostream>
// traits types
struct A {}; struct B {}; struct C {};
// helpers
void fun_impl(bool, A) { std::cout << "An"; }
void fun_impl(bool, B) { std::cout << "Bn"; }
// would like to eliminate this
void fun_impl(bool b, C)
{
if(b)
fun_impl(b, A());
else
fun_impl(b, B());
}
template<typename T>
void fun(bool b, T t)
{
// T = A, B, or C
fun_impl(b, t);
}
int main()
{
fun(true, A()); // "A"
fun(false, A()); // "A"
fun(true, B()); // "B"
fun(false, B()); // "B"
fun(true, C()); // "A"
fun(false, C()); // "B"
}
但是,此标记分发与函数fun
密切相关,我需要维护 3 个辅助函数来为每个使用它的函数实现此标记调度。
参数推导失败:我试图将fun_impl
抽象为 mixed_dispatch
函数对象的模板参数,但如果我随后fun_impl
作为参数传递,则无法推断出需要 2 个重载中的哪一个。
template<typename T>
struct mixed_dispatch
{
template<typename Fun>
void operator()(Fun f, bool b)
{
return f(b, T());
}
};
template<>
struct mixed_dispatch<C>
{
template<typename Fun>
void operator()(Fun f, bool b)
{
if (b)
return f(b, A());
else
return f(b, B());
}
};
template<typename T>
void fun(bool b, T)
{
// T = A, B, or C
mixed_dispatch<T>()(fun_impl, b); // ERROR: Fun cannot be deduced
}
问题:有没有其他方法可以将标签调度与被调用的函数分离?
我愿意接受使用 C++11 个可变参数模板/Boost.Fusion 或其他简化我当前代码的魔法的任何建议(我现在必须为每个使用此特定调度的函数维护 3 个而不是 2 个辅助函数,并且随着更复杂的调度,辅助函数的数量增长得更快)。
要选择重载函数之一,至少必须告诉编译器目标函数的参数类型。因此,我们可以将它们添加为模板类的类型参数mixed_dispatch
template < typename Tag, typename... Args >
class mixed_dispatch {
std::function<void(Tag,Args...)> invoke;
public:
// for overloaded functions
mixed_dispatch( void(&f)(Tag,Args...) ) : invoke( f ) { }
// for function objects
template < typename F >
mixed_dispatch( F&& f ) : invoke( std::forward<F>(f) ) { }
void operator()( Args... args ) const {
invoke( Tag(), args... );
}
};
现在mixed_dispatch
变成了一个包装器,可帮助您Tag
对象传递给目标函数。如您所见,我们需要更改目标函数的签名(位有效)。
void fun_impl(A1, bool) { std::cout << "A1n"; }
在客户端代码中,如fun
:
template< typename T >
void fun( bool b, T )
{
using dispatcher = mixed_dispatch<T,bool>;
dispatcher d = fun_impl;
d( b );
}
它能回答你的任何问题吗?
// traits types
struct A1 {}; struct B1 {};
struct A2 {}; struct B2 {};
template<class T1, class T2>
struct TypeSelector
{
typedef T1 TTrue;
typedef T2 TFalse;
};
typedef TypeSelector<A1, B1> C1;
typedef TypeSelector<A2, B2> C2;
// helpers
void fun_impl(bool, A1) { std::cout << "A1n"; }
void fun_impl(bool, B1) { std::cout << "B1n"; }
void fun_impl(bool, A2) { std::cout << "A2n"; }
void fun_impl(bool, B2) { std::cout << "B2n"; }
template<class TSel>
void fun_impl(bool b, TSel) { if(b) fun_impl(b, typename TSel::TTrue()); else fun_impl(b, typename TSel::TFalse()); }
template<typename T>
void fun(bool b, T t)
{
// T = A, B, or C
fun_impl(b, t);
}
int main()
{
fun(true, A1()); // "A1"
fun(false, A1()); // "A1"
fun(true, B1()); // "B1"
fun(false, B1()); // "B1"
fun(true, C1()); // "A1"
fun(false, C1()); // "B1"
fun(true, C2()); // "A2"
fun(false, C2()); // "B2"
}
或者你想简化其他"维度"中的代码?
相关文章:
- 为什么简单的算术减法在"if"条件下不起作用?
- 在什么条件下使用 std::memcpy 在对象之间复制是安全的?
- 改进简单条件下C++样式
- 唤醒多个线程以在每个条件下工作一次
- "is defined"宏检查及其调用必须处于不同的条件下吗?
- 在if条件下,右或左改变值的相等性检查是否有任何区别
- C++代码在 for 循环的条件下给出运行时错误,而如果它被具有相同意义的代码替换,则编译正确
- 在 constexpr-if 条件下比较 constexpr 函数参数会导致错误
- 轮班操作在条件下使用的说明
- 在不同条件下无法访问我的向量变量
- 在某些条件下最大化 GCD
- 如何更改此空隙函数,以便在特殊条件下返回一个生成的字符串
- 在if-Statement条件下与分配有关的错误
- 如何正确使用“ sizeof”操作员在循环的条件下正确使用
- 提升::MSM 检查保护条件下的状态转换
- C++在 IF 条件下递增
- C 在循环条件下忽略
- Bool Vector 2D数组在IF条件下使用
- 现代C++编译器是否能够避免在某些条件下两次调用常量函数
- 在混合运行时/编译时条件下调度标记