Переопределение стандартных функций

Я хотел бы переопределить поведение функции std, скажем, std::time. Можно ли вызвать std:: time и маршрутизировать ли это через мою пользовательскую функцию?

5 ответов

std Вообще говоря, пространство имен запрещено. Добавление новых функций, перегрузок, классов или чего-либо еще в std Пространство имен - ** неопределенное поведение *.

Единственным исключением являются шаблонные специализации. Вы можете предоставить специализации функций в std Пространство имен. Функция, где это часто делается, std::swap,

Это звучит как очень плохая идея. Вроде как переопределение true или же false, Лучше было бы написать собственную функцию-оболочку, скажем tim_time(), который может или не может позвонить std::time() внутренне.

Вместо того, чтобы называть это std::time, перенаправьте все вызовы, которые вы можете иногда переопределять, через другое пространство имен.

namespace mystd{
    using namespace std;
    void time() { ... }
}

// ...
mystd::time();  // not std::time
mystd::copy(...); // calls std::copy, unless you override it like time()

Тогда призыв к mystd::time вызовет модифицированную версию функции. Если вы вызываете не переопределенную функцию, например, mystd::copy, он будет правильно преобразован в исходную функцию std.

На некоторых платформах вы можете это осуществить. В исходном коде определите функцию, т.е.

extern "C" time_t time(time_t *value)
{
        ...
}

Если вам повезет, компоновщик свяжет вашу версию std::time более плотно, чем тот из стандартной библиотеки. Конечно, нет гарантии, что это сработает или будет связано так, как вы хотите. И как недостаток, у вас больше нет доступа к оригиналу std::time,

Как и все остальные, это не переносимое поведение. Я уверен, что это работает на Linux. Я также уверен, что это не работает в Windows (компоновщик жалуется на конфликт).

Не переносимо. Понимая, что стандарт не определяет, что происходит, вы обычно можете определять любые символы и функции, которые вам нравятся, в пространстве имен std, или ссылаться на библиотеку, которая определяет эти символы, или что угодно. Это просто неопределенное поведение. Так что все, что вы можете сделать - это пососать и посмотреть, и надеяться, что это не сломается в следующей версии вашего компилятора.

Тем не менее, с большинством компиляторов это, вероятно, будет работать в основном при условии, что вы избежите столкновения правил одного определения с "настоящим" std::time. Это связано с тем, что большинство компиляторов на самом деле не делают ничего особенного с пространством имен std, а заголовочные файлы и библиотеки, которые они используют для его реализации, ничем не отличаются от заголовочных файлов и библиотек, которые вы можете написать сами.

Дима абсолютно прав, однако, что выход за рамки стандарта почти всегда является очень плохой идеей. Может быть, если вы застряли в каком-то отладочном аду, где вы в основном хотите добавить протоколирование в std::time, но не можете, тогда стоит подумать. Иначе не ходи туда. Если вы хотите протестировать некоторый код, чтобы увидеть, правильно ли он работает в разное время, передайте этому коду параметр (или параметр шаблона), указывающий, какую функцию времени он должен вызывать.

Другие вопросы по тегам