Правильный ответ на ваш вопрос — не надо ) Не надо писать специализацию для первого шаблона. Если вы хотите написать что-то специфическое для int*, напишите
void foo(int*){}
Общее правило — не пишите специализацию, если можно решить проблему перегрузкой.
Имелось в виду, что раз все знаешь, то рабочий процесс не пострадает от того, что на него будет потрачено на полчаса меньше времени, легко наверстаешь, а если нет, то иди работай лучше, а то не успеешь )
Наверное, неясно выразил свою мысль.
Любую constexpr-функцию можно запустить в runtime, для этого достаточно передать аргумент, который нельзя посчитать на этапе компиляции.
Я скорее имел в виду всю фразу целиком
Параметры функций не могут быть constexpr. То есть не получится создать исключительно constexpr-функцию, которая может работать только на этапе компиляции.
Время вычисления функции зависит не от параметров (аргументов), а от того в каком контексте она используется. Например,
constexpr int foo(int i); // Здесь foo() может быть вычислена и в рантайме и в
const int j = foo(2); // компайлтайме, несмотря, что её аргументом является constexpr
constexpr int foo(int i); // А здесь foo() обязаны быть вызвана в
constexpr int j = foo(2); // компайлтайме
Я к тому, что у вас не то, чтобы неправильно написано, а немного непонятно, не на то акцент сделан.
В целом полезная статья, но бросились в глаза несколько неточностей/непонятностей.
constexpr int b = inc (a); // ошибка: преобразование int -> constexpr int
Это неверно. Ошибка в данном случае заключается не в том, что происходит попытка преобразования int в constexpr int, а в том, что a не является constexpr выражением, а такого типа, как constexpr int вообще не существует, так как constexpr не является частью типа, поэтому никаких попыток преобразования не делается.
То есть не получится создать исключительно constexpr-функцию, которая может работать только на этапе компиляции.
Вот это тоже непонятно.
constexpr int inc (int a)
{
return a + 1;
}
является как раз такой функцией, если я не ошибаюсь. Что может заставить эту функцию отрабатывать не в компайл тайме (кроме конкретной реализации компилятора)?
Также constexpr-функции могут работать с объектами, это будет рассмотрено позже.
Непонятная фраза. Могут работать с объектами? А обычные не могут?
С точки зрения накладных расходов в описанных вами примерах все хорошо, их нет =). В боевой реализации тупла нет строчки base_type& base = static_cast<base_type&>(*this);, поэтому sizeof(tuple<int>) == 4. Что качается лямбд, то они, как минимум такие же быстрые в рантайме, как и обычные функции, засчет того, что лямбда — это по сути неименованный функтор с объявленным внутри класса оператором вызова, который, как известно, в таких случаях является inline.
А при использовании CRTP такое возможно? Мне почему-то кажется, что тоже — нет.
А я разве писал, что CRTP решает эту проблему? Это не универсальное средство на все случаи жизни. Под какие-то архитектурные решения оно подходит, под другие — нет. И к тому же пакетная обработка все-таки возможна и и не слишком сложна с использованием доп. средств типа variant или fusion.
1. Именно в этом кусочке accept не нужна. Она оставлена из тех соображений, что вполне можно написать свой STL-like функцию алгоритм, в которой она уже будет использоваться аналогично тому, как используется в BGL.
2. Конечно, структуру person_visitor_t можно и нужно переделать в промышленном коде. Здесь она написана так, как она написана, чтобы показать близость предикатов и визитора.
3. Visitor вяжется с предикатами в том смысле что и то то является сходными механизмами диспетчеризации, отделения алгоритма от данных. Естественно ни один в один, но сходно. Об этом неплохо написано у товарища nickolaym в первом комментарии.
В этом предложении имелся в виду boost (std) function. В конце статьи про это немного написано. А под «ограничением» понимается скорее не ограничение хранения, а ограничение дальнейшего использования. Никто не запрещает хранить в function не callable объект. Но особого смысла в этом нет.
typeid, примененный к типу, отработает в compile time и в рантайме останется только сравнить два объекта type_info (что скорее всего сведется к сравнению 2х строк).
Да, вы правы. В примере действительно typeid отработает в compile time. Тут скорее речь шла о том, что сравнение типов все равно остается в рантайме, что медленнее полностью статической проверки, которая, к тому же, просто не дала бы скомпилироваться неверному приведению.
Да, вы правы, похоже сейчас это стало возможным без `union`, по крайней мере компилируется, работоспособность не проверял. Только компилировать нужно с другим флагом: `-fplan9-extensions`. Спасибо.
Union затем, чтобы можно было обращаться к базовому объекту по имени для передачи в код, ожидающий объект базового типа, т.е. для полиморфного использования в существующем коде и также чтобы возможно использовать данные базового объекта напрямую. В статье об этом есть.
Общее правило — не пишите специализацию, если можно решить проблему перегрузкой.
Наверное, неясно выразил свою мысль.
Я скорее имел в виду всю фразу целиком
Время вычисления функции зависит не от параметров (аргументов), а от того в каком контексте она используется. Например,
Я к тому, что у вас не то, чтобы неправильно написано, а немного непонятно, не на то акцент сделан.
Это неверно. Ошибка в данном случае заключается не в том, что происходит попытка преобразования
int
вconstexpr int
, а в том, чтоa
не являетсяconstexpr
выражением, а такого типа, какconstexpr int
вообще не существует, так как constexpr не является частью типа, поэтому никаких попыток преобразования не делается.Вот это тоже непонятно.
является как раз такой функцией, если я не ошибаюсь. Что может заставить эту функцию отрабатывать не в компайл тайме (кроме конкретной реализации компилятора)?
Непонятная фраза. Могут работать с объектами? А обычные не могут?
base_type& base = static_cast<base_type&>(*this);
, поэтомуsizeof(tuple<int>) == 4
. Что качается лямбд, то они, как минимум такие же быстрые в рантайме, как и обычные функции, засчет того, что лямбда — это по сути неименованный функтор с объявленным внутри класса оператором вызова, который, как известно, в таких случаях являетсяinline
.Тогда уж наверное даже так:
char const(&)[5]
=)Это да, поправил…
А я разве писал, что CRTP решает эту проблему? Это не универсальное средство на все случаи жизни. Под какие-то архитектурные решения оно подходит, под другие — нет. И к тому же пакетная обработка все-таки возможна и и не слишком сложна с использованием доп. средств типа variant или fusion.
2. Конечно, структуру person_visitor_t можно и нужно переделать в промышленном коде. Здесь она написана так, как она написана, чтобы показать близость предикатов и визитора.
3. Visitor вяжется с предикатами в том смысле что и то то является сходными механизмами диспетчеризации, отделения алгоритма от данных. Естественно ни один в один, но сходно. Об этом неплохо написано у товарища nickolaym в первом комментарии.