訪問者はオーバーロードで作業します。つまり、訪問者は静的コンポーネントです。ファクトリは常に(?)はランタイムコンポーネントを意味します。まず、派生したすべての訪問者が同じオーバーロードのセットを共有しているかどうかを判断することが重要です。その場合は、次のスキームを使用できます。
#include <memory>
#include <boost/variant.hpp>
#include <boost/variant/static_visitor.hpp>
struct visitor_base : public boost::static_visitor<int>
{
virtual int operator()(int) = 0;
virtual int operator()(double) = 0;
virtual int operator()(const char*) = 0;
virtual ~visitor_base() {}
};
struct impl_1 : visitor_base {
virtual int operator()(int) { return 1; }
virtual int operator()(double) { return 1; }
virtual int operator()(const char*) { return 1; }
};
struct impl_2 : visitor_base {
virtual int operator()(int) { return 2; }
virtual int operator()(double) { return 2; }
virtual int operator()(const char*) { return 2; }
};
std::unique_ptr<visitor_base> visitor_factory(int i) {
if(i == 1) {
return std::unique_ptr<visitor_base>(new impl_1);
} else {
return std::unique_ptr<visitor_base>(new impl_2);
}
}
int main()
{
auto vis = visitor_factory(1);
boost::variant<int, double, const char*> v = 3;
std::cout << boost::apply_visitor(*vis, v) << std::endl;
auto vis2 = visitor_factory(2);
std::cout << boost::apply_visitor(*vis2, v) << std::endl;
return 0;
}
派生訪問者がバリアント内の可能なタイプのサブセットにのみ適用することを目的としている場合、純粋仮想関数を使用することはできず、ベースの値を処理するための失敗を報告するメカニズムが必要です(例外など)。
もちろん、サンプルコードで使用されているいくつかのC ++ 11機能は、簡単に置き換えることができます。
#include <memory>
#include <string>
#include <boost/variant.hpp>
#include <boost/variant/static_visitor.hpp>
struct visitor_base : public boost::static_visitor<int>
{
// the catch all
template <typename T>
int operator()(const T& t) {
return 0;
}
virtual int operator()(int) {}
virtual int operator()(double) {}
virtual int operator()(const char*) {}
virtual ~visitor_base() {}
};
struct impl_1 : visitor_base {
virtual int operator()(int) { return 1; }
virtual int operator()(double) { return 1; }
virtual int operator()(const char*) { return 1; }
};
struct impl_2 : visitor_base {
virtual int operator()(int) { return 2; }
virtual int operator()(double) { return 2; }
virtual int operator()(const char*) { return 2; }
};
std::unique_ptr<visitor_base> visitor_factory(int i) {
if(i == 1) {
return std::unique_ptr<visitor_base>(new impl_1);
} else {
return std::unique_ptr<visitor_base>(new impl_2);
}
}
int main()
{
auto vis = visitor_factory(1);
boost::variant<int, double, const char*> v = 3;
std::cout << boost::apply_visitor(*vis, v) << std::endl;
auto vis2 = visitor_factory(2);
std::cout << boost::apply_visitor(*vis2, v) << std::endl;
// a variant with more than impl_1 and impl_2 can catch
boost::variant<int, double, const char*, std::string> vv = std::string{"asdf"};
std::cout << boost::apply_visitor(*vis2, vv) << std::endl;
// no use one that we handle
vv = 3;
std::cout << boost::apply_visitor(*vis2, vv) << std::endl;
return 0;
}