Pull to refresh
18
0.5

Инженегр АСУТП

Send message
На самом деле, перекомпилировать не нужно. Это же Си — обычные константы!
Просто новые Визиторы должны видеть дополненный enum.

Вот интересно скорость сравнить — мой вариант сравнить с табличкой производительности.
Ассемблерный код switch я уже посмотрел — 2 инструкции сравнения )
Это Cyclic Visitor, только завернут в шаблоны.
А, действительно. Но как пишет Александреску — это самый неудачный паттерн, потому редко используемый.

В вашем примере в итоге весь выигрыш из-за неудачной реализации dynamic_cast, который вы с помощью 3х листов исходного кода, с блекджеком и шаблонами реализуете руками с помощью map<>.

На мой взгляд, не нужно множить сущности, http://ideone.com/K0KQhk вот реализация проще, расширяемая и более эффективная, т.к switch() отлично оптимизируется компилятором
Заголовок спойлера
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
enum e_type {
	ENTITY,
	GEOMETRY,
	MODEL
};

struct visitor_base;
struct visitable 
{
    virtual void accept(visitor_base & obj) = 0;
};

struct visitor_base
{
    virtual void visit(visitable &, enum e_type type) = 0;
};

struct entity : visitable
{
    void accept(visitor_base & obj)
    {
        obj.visit(*this, ENTITY);
    }
};

struct geometry : entity
{
	void accept(visitor_base & obj)
    {
        obj.visit(*this, GEOMETRY);
    }
};

struct model : geometry
{
    void accept(visitor_base & obj)
    {
        obj.visit(*this, MODEL);
    }
};

struct test_visitor : visitor_base
{
    void visit(visitable & obj, enum e_type type)
    {
		switch(type)
		{
			case	ENTITY:
				{
					entity	&ent = (entity&)obj;  // its enough safe
					cout << "Visited ENTITY" << endl;
					break;
				}
			case	GEOMETRY:
				{
					geometry	&geo = (geometry&)obj;
					cout << "Visited GEOMETRY" << endl;
					break;
				}
			case	MODEL:
				{
					model	&mod = (model&)obj;
					cout << "Visited MODEL" << endl;
					break;
				}
			default:
				// TRAP
				;
		}
	}
};

struct modern_visitor : test_visitor // extension for new objects
{
	// add new methods for new visitables, call parent otherwise
};


int main() {
	entity E;
	geometry G;
	model M;
	vector<entity*> vec = {&E, &G, &M};
	test_visitor visi;
	for_each(vec.begin(), vec.end(), [&](entity *i){ i->accept(visi); });

	// your code goes here
	return 0;
}

Непонятно, зачем нужен dynamic_cast<geometry_visitor*>(&obj)) в типичной реализации, если obj.visit() — виртуальный? Соответственно, вызов виртуального метода быстрее, чем RTTI.
Ну и тогда проблемы, которая решается в статье, нет вообще.
Есть более-менее стандартное решение в виде Boost Multi-index Конечно, если огромный бюст вас не пугает в проекте.
А зачем работать с указателями, когда можно обойтись индексами? Тип фиксирован, максимальный размер известен, зачем городить указатели?
Ммм, ну я не знаю, откуда ты взял проблемы в своем п.3

Индексы в С это и есть указатели, точнее смещение к указателю.

Ладно, с алгоритмом обращения я похоже спутал какой то другой алгоритм, который в новостях недавно пробегал.

Прекращаю оффтопить.
Вообще то статья не о качестве исходного кода, а об оптимизации.

STL наоборот, дает еще преимущества отсутствия необходимости работы с указателями и дает некоторую защиту от выхода за рейнж при отладке.

Зачем оптимизировать метод Гаусса компилятором или пытаться прикрутить к нему STL, если есть гораздо более эффективные _алгоритмы_? Неудачный пример, но не надо конечно везде совать шаблоны, согласен.

Статически или на стеке — для скорости работы не важно. Но невозможно для компилятора создать объект неизвестного заранее размера с фиксированным адресом. Да и не нужно.
Пример стекового аллокатора я привел, как оптимизация в плане исключения запросов выделения памяти ОС.

Я уже пытался ему объяснить вкус устриц.

Если вкратце, то стоит просто посмотреть, в какой машинный код превращается программа с использованием STL при компиляции с разной степенью оптимизации. Тогда можно начинать спорить.

Смотреть после опытов
Как ни странно, но STL-шаблоны бывают эффективнее С-кода. И можно сделать кастомный аллокатор на стеке, если смущает куча.
Язык это не так уж сложно. Проблема в объеме современных фреймворков
Через несколько — на том же. А вот через десять…

На С
В общем понятно, что Вы, с помощью некоторой ловкости рук, хотите объявить несостоятельным формат IEEE754 и предложить свою модификацию или даже новейшую разработку.

Будет интересно посмотреть.

Я недавно столкнулся с задачей реализовать стандартный набор С-функций math.h на ассемблере. В процессе чего выяснилось — что набор инструкций, удобный процессору, во многом перпендикулярен привычным человеку математическим функциям.

Соответственно, разрабатывая новый формат, Вам нужно спроектировать к нему и набор инструкций, эффективно с ним работающий.

Удачи.
Единственное, чем полезна эта статья, это напоминанием о шестнадцатеричном представлении ЧПТ, тем что Excel работает исключительно с float и об относительной точности вычислений, которую мы правда увидели уже только в обсуждении =)
Именно, Innotor просто мухлюет. Примерно так 0.13+0.13+0,1 ~= 0,4
http://ideone.com/Xwe4vV

И что же мы видим — исходная предпосылка для первого числа неверная — число 0.6000006 не существует в виде float, и из нее рождается демагогия.
Инструкции BCD устарели и с переходом на x64 убраны.
Я бы в подобный случаях советовал использовать hexfloat (%a) формат, чтобы различить, где у вас исходная десятичная константа уже с округлением.

  cout << 0x0.123p-1 << endl;
  cout << std::hexfloat << 6.6;
Во первых, FPU выполняет вычисления с внутренней точностью, далеко превосходящей даже long double (10-байт). Усечение происходит «на выходе».
Да похоже я слегка загнул — внутренние вычисления происходят в x87 в 80-битном виде. Т.е операнды расширяются к 80-бит, выполняются вычисления и после этого происходит обратная конверсия с понижением точности.

Если же используются SSE/AVX то там максимум 64-бит числа с плавающей точкой.

Утверждается (например на stackoverflow), что с предварительным расширением до 80-бит и без него можно получить разные результаты вычислений.
Дело не только в формате представления чисел.

Во первых, FPU выполняет вычисления с внутренней точностью, далеко превосходящей даже long double (10-байт). Усечение происходит «на выходе»

Во вторых, на самом деле FPU считает «не совсем по стандарту». В тоже же библиотеке, например GCC, масса воркэраундов. AFAIK -ffast-math будет выполнять расчеты только инструкциями FPU, и результат может вас удивить.
Но нужно немного подождать =)
Хорошая статья и просто написано. Жаль не указана версия gcc, но с векторизацией что gcc что msvc пока только делают первые робкие шаги.

Information

Rating
1,884-th
Location
Россия
Registered
Activity