Если вы можете позволить себе Boost, то это звучит как идеальное приложение для Boost.Variant .
struct NoIntersection {
// empty
};
struct Point {
// whatever
};
struct Circle {
// whatever
};
typedef boost::variant<NoIntersection, Point, Circle> IntersectionResult;
IntersectionResult intersection_test() {
if(some_condition){
return NoIntersection();
}
if(other_condition){
return Point(x, y);
}
if(another_condition){
return Circle(c, r);
}
throw std::runtime_error("unexpected");
}
Затем вы обрабатываете свой результат с помощью статического посетителя:
struct process_result_visitor : public boost::static_visitor<> {
void operator()(NoIntersection) {
std::cout << "there was no intersection\n";
}
void operator()(Point const &pnt) {
std::cout << "there was a point intersection\n";
}
void operator()(Circle const &circle) {
std::cout << "there was a circle intersection\n";
}
};
IntersectionResult result = intersection_test();
boost::apply_visitor(process_result_visitor(), result);
РЕДАКТИРОВАТЬ: Класс посетителя должен происходить из boost::static_visitor
ОБНОВЛЕНИЕ: В ответ на некоторые критические комментарии я написал небольшую программу для тестирования . Четыре подхода сравниваются:
boost::variant
- союз
- иерархия классов
boost::any
Это результаты на моем домашнем компьютере, когда я компилирую в режиме выпуска с оптимизацией по умолчанию (VC08):
тест с бустом :: вариант занял 0,011 мкс
тест с объединением занял 0,012 мкс
тест с иерархией занял 0,227 мкс
тест с бустом :: любой занял 0,188 мкс
Использование boost::variant
быстрее объединения и приводит (IMO) к самому элегантному коду. Я предполагаю, что крайне низкая производительность подхода иерархии классов связана с необходимостью использования динамического выделения памяти и динамического распределения. boost::any
не является ни быстрым, ни особенно элегантным, поэтому я бы не стал рассматривать его для этой задачи (хотя есть и другие приложения)