Variant Sınıfı
variant Sınıfı yazısına taşıdım.
Visitor
Şu satırı dahil ederiz.
Örnek 1
İstersek bazı template tipleri için metod yazıp geri kalanını hep aynı yere yönlendirebiliriz. Şöyle yaparız.
Örnek 2
Functor return type tanımlanması isteyebilir. Örneğin tüm tiplere ++ işlemi yapmak istersek şöyle yaparız.
bool tipi için Add işlemini gerçekleştiremeyen bir polymorphic functor yazmak için şöyle yaparız.
Şöyle çağrılır.
Tüm nesnelerin somet_operation metodu olduğunu varsayarak şöyle yaparız.
variant Sınıfı yazısına taşıdım.
Visitor
Şu satırı dahil ederiz.
#include <boost/variant.hpp>
Visitor Tanımlama
Visitor şöyle tanımlanır. Visitor variant içindeki tüp tipler için bir operator()(X) tanımlamalıdır. Yoksa derleme hatası alırız.struct as_int_visitor : boost::static_visitor<int> {
int operator()(std::string const& s) const { return std::stoi(s); }
int operator()(int i) const { return i; }
};
void dönen visitor şöyle tanımlanır.struct visitor : boost::static_visitor<>
{
void operator()(const int& i) const { ... }
void operator()(const std::string & str) const { ... }
};
Template Visitor Tanımlama
Template kullanan visitor şöyle tanımlanır.
Template kullanan visitor şöyle tanımlanır.
struct GetVector : public boost::static_visitor<double>
{
template<typename T>
double operator() (const T& v)
{...}
};
Template birden fazla parametre alabilir.struct ADD {};
struct DEL {};
class MultiVisitor : public boost::static_visitor<void> {
public:
template <typename T, typename U>
void operator()(T& t, const U& u) {
t.visit(u);
}
};
static MV const add = ADD();
static MV const del = DEL();
MultiVisitor mv;
for (TShapes& shape : tshapes) {
boost::apply_visitor(mv, shape, add);
boost::apply_visitor(mv, shape, del);
}
Polymorphic Functor ya da Template FunctorÖrnek 1
İstersek bazı template tipleri için metod yazıp geri kalanını hep aynı yere yönlendirebiliriz. Şöyle yaparız.
struct IsNullThing {
bool operator()(Null) const { return true; }
template <typename T> bool operator()(T) const { return false; }
template <typename... Ts> bool operator()(boost::variant<Ts...> const& v) const{
return boost::apply_visitor(*this, v);
}
};
Bunu şöyle kullanırız.IsNullThing isNullThing;
// and just call it
MyVariant v;
bool ok = isNullThing(v);
Functor return type tanımlanması isteyebilir. Örneğin tüm tiplere ++ işlemi yapmak istersek şöyle yaparız.
namespace detail {
struct incrementer {
template< typename T >
void operator()(T& x) const { ++x; }
typedef void result_type;
};
}
void incr(AnyIterator& ai)
{
boost::apply_visitor(detail::incrementer(),ai);
}
Örnek 3bool tipi için Add işlemini gerçekleştiremeyen bir polymorphic functor yazmak için şöyle yaparız.
struct Add : public boost::static_visitor<VariantType> {
template <typename T, typename U>
auto operator() (T a, U b) const -> decltype(a+b) { return a + b; }
template <typename T> VariantType operator()(bool, T) const {
throw std::invalid_argument("Can't to bool"); }
template <typename T> VariantType operator()(T, bool) const {
throw std::invalid_argument("Can't add bool"); }
VariantType operator()(bool,bool) const {
throw std::invalid_argument("Can't add bools"); }
};
Şöyle çağırırız.using VariantType = boost::variant<int, float, double, bool>;
int main() {
std::cout << std::boolalpha;
VariantType specimens[] = { int(42), 3.14f, 3.14, true };
for (auto lhs : specimens)
for (auto rhs : specimens)
{
try {
std::cout << lhs << " + " << rhs << " == " <<
boost::apply_visitor(Add{}, lhs, rhs) << "\n";
} catch(std::exception const& e) {
std::cout << lhs << " + " << rhs << " ==> " << e.what() << "\n";
}
}
}
Çıktı olarak şunu alırız.42 + 42 == 84
42 + 3.14 == 45.14
42 + 3.14 == 45.14
42 + true ==> Can't add bool
3.14 + 42 == 45.14
3.14 + 3.14 == 6.28
3.14 + 3.14 == 6.28
3.14 + true ==> Can't add bool
3.14 + 42 == 45.14
3.14 + 3.14 == 6.28
3.14 + 3.14 == 6.28
3.14 + true ==> Can't add bool
true + 42 ==> Can't to bool
true + 3.14 ==> Can't to bool
true + 3.14 ==> Can't to bool
true + true ==> Can't add bools
Visitor ÇağırmaŞöyle çağrılır.
boost::apply_visitor(some_visitor(), myvariant);
Daha kolay çağırma için genelde yardımcı bir metod kullanılır.int as_int(StringOrInt const& v) {
return apply_visitor(as_int_visitor{}, v);
}
Şöyle çağırırız.for (int i = values.size()-1; i > 0; --i)
std::cout << as_int(values[i]);
C++14 ile Template LambdaTüm nesnelerin somet_operation metodu olduğunu varsayarak şöyle yaparız.
boost::apply_visitor([](auto const& obj) { obj.some_operation(); }, v);
Hiç yorum yok:
Yorum Gönder