Пишу шаблон функции:
template <class T> void fun(T tt){
//здесь какая-то работа с tt
}
Теперь хочу, чтобы если тип T маленький, то чтобы при инстанцировании параметр передавался по значению:
void fun(little_struct tt){
//здесь какая-то работа с tt
}
А если если тип T большой, то чтобы при инстанцировании параметр передавался по ссылке:
void fun(big_struct& tt){
//здесь какая-то работа с tt
}
Вопросы:
Вариант с одной функцией
template<class T>
void foo(typename std::conditional_t<(sizeof(T) <= sizeof(void*)) && std::is_trivially_copyable_v<T>, T, const T&> arg)
{
}
Но так компилятор не может вывести T
. Мне на ум не приходит как это разрешить при помощи шаблонов. Так что могу предложить вам писать
foo<Type>(arg)
или сделать макрос
#define foo(arg) foo_impl<decltype(arg)>(arg)
Так не годится?
template<typename T, typename = enable_if_t<sizeof(T) <= 2>>
void f(T)
{
cout << "By value\n";
};
template<typename T, typename = enable_if_t<(sizeof(T) > 2)>>
void f(const T&)
{
cout << "By reference\n";
};
int main(int argc, const char * argv[])
{
f(short(3));
f(3);
}
Можно поиграться в игру conditional
template<typename T>
void f(typename conditional_t<sizeof(T) <= 2,T,const T&> t)
{
if (is_reference_v<decltype(t)>)
cout << "By reference\n";
else
cout << "By value\n";
};
но тогда надо явно указывать тип при вызове -
f<short>(3);
f<int>(3);
Что-то в голове вертится, как обойти... но никак не доверчивается :), а другой работы хватает. Если подсознание само решит проблему :) - допишу.
Нельзя менять тип и при этом сохранять deducible context (т.е. не указывать тип при вызове). Но в С++ почти всё, что не решается напрямую, решается косвенным образом. Поэтому нужно просто ввести один уровень косвенности. Вашу функцию с кодом мы немного переименуем и будет она выглядеть так:
template <class T> void fun_impl(T tt)
{
//...
}
А теперь напишем вспомогательную функцию, которая за нас сделает всю необходимую работу:
template <class T> void fun(T&& tt)
{
using Pure_t = std::decay_t<T>;
constexpr bool isBig = sizeof(T) > 16;
if constexpr(isBig)
fun_impl<Pure_t&>(tt);
else
fun_impl<Pure_t>(tt);
}
Вот и всё. Можно добавить ещё пачку булевых переменных, чтобы охватить вектора, строки и прочее — всё это добавляется элементарно.
P.S. Я надеюсь, что интерес тут сугубо академический, потому что в подобном разграничении нет никакого смысла. Подобным функциям не место в реальном коде.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Имеется матрица (допустим 3x3) которая применяется для преобразования некоего массива двумерных точек (допустим std::vector<Point>)Как это грамотно...
Есть проблема определения команд СonfigParser'омВыполнял следующую последовательность действий:
Если функция является зарезервированным набором команд в памяти, то могу ли я её удалить? Если да, то как?
Есть ли готовый список шрифтов для html страницы, что бы можно было подключить в несколько строчек кода? Под список шрифтов я имею ввиду выпадающий...