一个重要的问题是有效载荷有何不同,以及它们有何相同之处。在某些情况下,您可以生成由有效负载确定类型的对象,然后通过所有有效负载类型通用的虚拟接口与它们交互的系统。
另一个选项假设您有一个有限且固定的有效负载类型列表,返回 aboost::variant
相对容易。然后为了处理它,调用apply_visitor
一个接受变体中每种类型的函子。
如果您只想以不同的方式处理一种类型的有效负载,那么“当且仅当类型与 T 匹配时调用并运行 lambda”函数并不难以这种方式编写。
所以你可以得到这样的语法:
struct State;
struct HandlePayload
{
typedef void return_type;
State* s;
HandlePayload(State* s_):s(s_) {}
void operator()( int const& payload ) const {
// handle int here
}
void operator()( std::shared_ptr<bob> const& payload ) const {
// handle bob ptrs here
}
template<typename T>
void operator()( T const& payload ) const {
// other types, maybe ignore them
}
}
这很可爱,但你会注意到它是非常间接的。但是,您还会注意到,您可以使用上面的通用类型 T 编写模板代码来处理有效负载,并在某些情况下使用诸如特征类之类的东西,或者在其他情况下使用显式特化。
如果您希望有效负载是一种特定类型,并且只想在这种情况下做一些特殊工作,那么在 a 上编写单一类型的处理程序boost::variant
很容易。
template<typename T, typename Func>
struct Helper {
typedef bool return_type;
Func f;
Helper(Func f_):f(f_) {}
bool operator()(T const& t) {f(t); return true; }
template<typename U>
bool operator()(U const& u) { return false; }
};
template<typename T, typename Variant, typename Func>
bool ApplyFunc( Variant const& v, Func f )
{
return boost::apply_visitor( Helper<T, Func>(f), v );
}
它将在变体 v 上调用 f 但仅在变体中的类型 T 上调用,如果类型匹配则返回 true 。
使用它,您可以执行以下操作:
boost::variant<int, double> v = 1.0;
boost::variant<int, double> v2 = int(1);
ApplyFunc<double>( v, [&](double d) { std::cout << "Double is " << d << "\n"; } );
ApplyFunc<double>( v2, [&](double d) { std::cout << "code is not run\n"; } );
ApplyFunc<int>( v2, [&](int i) { std::cout << "code is run\n"; } );
或一些这样的变体。