#include <iostream>

#include <memory>

#include <vector>

#include <boost/range/adaptor/indirected.hpp>

#include <boost/variant.hpp>



struct Background {

void update()

{

std::cout << "background" << std::endl;

}

};


struct Character {

void update()

{

std::cout << "character" << std::endl;

}

};


struct Effect {

void update()

{

std::cout << "effect" << std::endl;

}

};


struct UpdateVisitor {

using result_type = void;


template <class T>

void operator()(T& x)

{

x.update();

}

};


class TaskList {

using TaskType = boost::variant<Background, Character, Effect>;

std::vector<TaskType> taskList_;

public:

void update()

{

for (TaskType& x : taskList_) {

UpdateVisitor vis;

boost::apply_visitor(vis, x);

}

}


template <class Task, class... Args>

void add(Args... args)

{

taskList_.push_back(Task(args...));

}

};


int main()

{

TaskList task;

task.add<Background>();

task.add<Character>();

task.add<Effect>();


task.update();


return 0;

}


위 구현을 기존에는 아래처럼 인터페이스를 상속해서 구현하였다.

struct UpdateInterface {

virtual void update() = 0;

};


struct Background : public UpdateInterface {

void update() override

{

std::cout << "background" << std::endl;

}

};


struct Character : public UpdateInterface {

void update() override

{

std::cout << "character" << std::endl;

}

};


struct Effect : public UpdateInterface {

void update() override

{

std::cout << "effect" << std::endl;

}

};


class TaskList {

std::vector<std::unique_ptr<UpdateInterface>> taskList_;

public:

void update()

{

for (UpdateInterface& x : taskList_ | boost::adaptors::indirected) {

x.update();

}

}


template <class Task, class... Args>

void add(Args... args)

{

taskList_.push_back(std::unique_ptr<UpdateInterface>(new Task(args...)));

}

};


int main()

{

TaskList task;

task.add<Background>();

task.add<Character>();

task.add<Effect>();


task.update();

}


// 출처: https://sites.google.com/site/boostjp/tips/variant

저작자 표시
신고
by 흥배 2014.06.19 08:00

#include <iostream>

#include <string>

#include <boost/variant.hpp>


struct var_printer : boost::static_visitor<void> {

void operator()(int x) const

{

std::cout << x << std::endl;

}


void operator()(std::string& s) const

{

std::cout << s << std::endl;

}


void operator()(double x) const

{

std::cout << x << std::endl;

}

};


int main()

{

std::cout << "저장" << std::endl;

{

boost::variant<int, std::string, double> v;


// 빈 상태

std::cout << v.which() << std::endl;


v = 1; // int 타입의 값 저장

std::cout << v.which() << std::endl;


v = 3.14; // double 타입의 값 저장

std::cout << v.which() << std::endl;

}


std::cout << "타입 판정" << std::endl;

{

boost::variant<int, std::string, double> v;


v = 1; // int 타입의 값 저장

if (v.type() == typeid(int)) {

std::cout << "int" << std::endl;

}


v = 3.14; // double 타입의 값 저장

if (v.type() == typeid(double)) {

std::cout << "double" << std::endl;

}

}


std::cout << "값 얻기" << std::endl;

{

boost::variant<int, std::string, double> v;

v = 1;


// 참조

try {

int& x = boost::get<int>(v);

std::cout << x << std::endl;

}

catch (boost::bad_get& e) {

std::cout << e.what() << std::endl;

}


// 포인터

if (int* x = boost::get<int>(&v)) {

std::cout << *x << std::endl;

}

else {

std::cout << "int 값은 저장 되어 있지 않다." << std::endl;

}

}


std::cout << "값 비우기" << std::endl;

{

boost::variant<boost::blank, int, std::string> v = boost::blank();

v = 3;


v = boost::blank();


if (v.type() == typeid(boost::blank)) {

std::cout << "blank" << std::endl;

}

else {

std::cout << "no blank" << std::endl;

}

}


std::cout << "타입에 맞는 함수 호출하기" << std::endl;

{

// int, string, double

boost::variant<int, std::string, double> v;


v = 3; // int

boost::apply_visitor(var_printer(), v); // visitor으로 타입에 맞는 처리를 한다.


v = "hello"; // string

boost::apply_visitor(var_printer(), v);

}



return 0;

}

// 출처: https://sites.google.com/site/boostjp/tips/variant

저작자 표시
신고
by 흥배 2014.06.18 08:00
| 1 |

티스토리 툴바