Пожалуйста, обратите внимание следующее tree
классаКонструктор дизайна для класса, который делегирует значение одной из переменных членов
template<typename T>
class tree
{
public:
template<typename U>
tree(U&& value)
: m_value(std::forward<U>(value))
{ }
private:
T m_value;
};
и некоторый многословный класс foo
который строится его std::string name
, который печатается через std::cout
всякий раз, когда один из его конструкторы вызываются.
foo a("a"), b("b");
foo const c("c");
tree<foo> s(std::move(a)), t(b), u(c);
дает следующий результат:
a constructed
b constructed
c constructed
a moved
b copied
c copied
, которое, как ожидалось.
Как это работает?
Чтобы быть конкретным: Мы не можем использовать
tree(T&& value)
: m_value(std::forward<T>(value))
{ }
Почему? Ну, потому что мы вынуждаем decltype(value)
быть foo&&
, которого нет в t(b)
и u(c)
. Нам нужно будет предоставить
tree(T const& value)
: m_value(value)
{ }
также, если мы хотим использовать этот спорный вариант. Ctor, используемый в работе по внедрению tree
, является причиной reference collapsing rules.
Но почему мы не можем использовать
template<typename U> tree(U&& value) : m_value(std::forward<T>(value)) { }
вместо этого?
Ну, причина в том, что в u(c)
мы имеем U = foo const& = decltype(value)
, но std::forward<T>
принимает только foo&
или foo&&
, так как T = foo
. Напротив, std::forward<U>
принимает foo const&
(или foo const&&
), начиная с U = foo const&
.
Так что, если я не с видом что-то, что мы должны использовать
template<typename U> tree(U&&)
вместоtree(T const&)
,tree(T&&)
комбинации. Но: компилятор приметtemplate<typename U> tree(U&&)
CTOR вpush_back
, где намерены в том, что движение к т е р оtree
принимается:
foo a("a"), b("b");
foo const c("c");
tree<foo> t("root");
t.emplace_back(std::move(a));
t.emplace_back(b);
t.emplace_back(c);
tree<foo> u("other root");
u.push_back(t); // cannot convert argument 1 from 'tree<foo>' to 'std::string const&'
Что я могу сделать? Нужно ли вместо этого использовать комбинацию
tree(T const&)
,tree(T&&)
?
[Извините за слишком многословным, но я чувствовал себя ответственным за прояснении любой технический вопрос, прежде чем просить для дизайна.]
Мы можем объявить 'template tree (U &&)' '' '' 'явным'. Тогда «t = 20» было бы невозможно. –
0xbadf00d
@ 0xbadf00d Вот что я написал в своем последнем абзаце, да. Хотя, вероятно, это не так понятно. –