Сообщение Re[8]: Cоздание базового шаблона минуя специализацию от 11.11.2022 13:02
Изменено 11.11.2022 13:09 rg45
Re[8]: Cоздание базового шаблона минуя специализацию
Здравствуйте, Videoman, Вы писали:
V>Кстати с wrapper-ом точно что-то не то, т.к. T&& у wrapper(T&& t) не является универсальной ссылкой. Наверное должно быть так:
Все верно, wrapper<T> не использует механизм perfect forwarding непосредственно, но он перенимает результаты использования perfect forwarding у функции wrap как эстафетную палочку. Если ты будешь создавать объект wrapper<T> непосредсвенно, минуя функцию wrap, то T — это тот тип, которым ты параметризовал шаблонный класс wrapper, и ни о каких perfect forwarding ссылках, конечно же, не может быть и речи при таком использовании. Если же ты создаешь объект wrapper<T> через функцию wrap, то T — это тип, выведенный при матчинге настоящей perfect forwarding ссылки, являющейся параметром функции wrap. В этом случае Т — это может быть как тип объекта, так и lvalue сылка на объект и результат будет ровно таким же, как если бы функция возвращала бы результат напрямую, без враппинга:
http://coliru.stacked-crooked.com/a/0e46aaa5c625351b
V>Кстати с wrapper-ом точно что-то не то, т.к. T&& у wrapper(T&& t) не является универсальной ссылкой. Наверное должно быть так:
V>template<typename U>
V>explicit wrapper(U&& t) : t(std::forward<U>(t)) {}
V>
Еще есть вариант что библиотека fmt обрабатывает стандартные типы внутри себя, без использования fmt::formatters, и из-за этого вся последовательность логики ломается. Все верно, wrapper<T> не использует механизм perfect forwarding непосредственно, но он перенимает результаты использования perfect forwarding у функции wrap как эстафетную палочку. Если ты будешь создавать объект wrapper<T> непосредсвенно, минуя функцию wrap, то T — это тот тип, которым ты параметризовал шаблонный класс wrapper, и ни о каких perfect forwarding ссылках, конечно же, не может быть и речи при таком использовании. Если же ты создаешь объект wrapper<T> через функцию wrap, то T — это тип, выведенный при матчинге настоящей perfect forwarding ссылки, являющейся параметром функции wrap. В этом случае Т — это может быть как тип объекта, так и lvalue сылка на объект и результат будет ровно таким же, как если бы функция возвращала бы результат напрямую, без враппинга:
http://coliru.stacked-crooked.com/a/0e46aaa5c625351b
#include <iostream>
template <typename T>
struct wrapper
{
T t;
explicit wrapper(T&& t) : t(std::forward<T>(t)) {}
T&& forward() { return std::forward<T>(t); }
};
template <typename T>
wrapper<T> wrap(T&& t) { return wrapper<T>(std::forward<T>(t)); }
int main()
{
int value = 42;
std::cout << "Value before: " << value << std::endl;
wrap(value).t = 43;
std::cout << "Value after: " << value << std::endl;
}
Re[8]: Cоздание базового шаблона минуя специализацию
Здравствуйте, Videoman, Вы писали:
V>Кстати с wrapper-ом точно что-то не то, т.к. T&& у wrapper(T&& t) не является универсальной ссылкой. Наверное должно быть так:
Все верно, wrapper<T> не использует механизм perfect forwarding непосредственно, но он перенимает результаты использования perfect forwarding у функции wrap как эстафетную палочку. Если ты будешь создавать объект wrapper<T> непосредсвенно, минуя функцию wrap, то T — это тот тип, которым ты параметризовал шаблонный класс wrapper, и ни о каких perfect forwarding ссылках, конечно же, не может быть и речи при таком использовании. Если же ты создаешь объект wrapper<T> через функцию wrap, то T — это тип, выведенный при матчинге настоящей perfect forwarding ссылки, являющейся параметром функции wrap. В этом случае Т — это может быть как тип объекта, так и lvalue сылка на объект и результат будет ровно таким же, как если бы функция возвращала бы результат напрямую, без враппинга — T wrap(T&&):
http://coliru.stacked-crooked.com/a/0e46aaa5c625351b
V>Кстати с wrapper-ом точно что-то не то, т.к. T&& у wrapper(T&& t) не является универсальной ссылкой. Наверное должно быть так:
V>template<typename U>
V>explicit wrapper(U&& t) : t(std::forward<U>(t)) {}
V>
Еще есть вариант что библиотека fmt обрабатывает стандартные типы внутри себя, без использования fmt::formatters, и из-за этого вся последовательность логики ломается. Все верно, wrapper<T> не использует механизм perfect forwarding непосредственно, но он перенимает результаты использования perfect forwarding у функции wrap как эстафетную палочку. Если ты будешь создавать объект wrapper<T> непосредсвенно, минуя функцию wrap, то T — это тот тип, которым ты параметризовал шаблонный класс wrapper, и ни о каких perfect forwarding ссылках, конечно же, не может быть и речи при таком использовании. Если же ты создаешь объект wrapper<T> через функцию wrap, то T — это тип, выведенный при матчинге настоящей perfect forwarding ссылки, являющейся параметром функции wrap. В этом случае Т — это может быть как тип объекта, так и lvalue сылка на объект и результат будет ровно таким же, как если бы функция возвращала бы результат напрямую, без враппинга — T wrap(T&&):
http://coliru.stacked-crooked.com/a/0e46aaa5c625351b
#include <iostream>
template <typename T>
struct wrapper
{
T t;
explicit wrapper(T&& t) : t(std::forward<T>(t)) {}
T&& forward() { return std::forward<T>(t); }
};
template <typename T>
wrapper<T> wrap(T&& t) { return wrapper<T>(std::forward<T>(t)); }
int main()
{
int value = 42;
std::cout << "Value before: " << value << std::endl;
wrap(value).t = 43;
std::cout << "Value after: " << value << std::endl;
}