Информация об изменениях

Сообщение Re[8]: Cоздание базового шаблона минуя специализацию от 11.11.2022 13:02

Изменено 11.11.2022 13:09 rg45

Re[8]: Cоздание базового шаблона минуя специализацию
Здравствуйте, Videoman, Вы писали:

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) не является универсальной ссылкой. Наверное должно быть так:
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;
}