2015-05-24 2 views
1

Спецификация std::decay в N4296 оставляет следующее примечание:Каковы различия между std :: decay и pass-by-value?

[Примечание: Это поведение похож на Lvalue-к-Rvalue (4.1), массив к указателю (4.2), и функции к указателю (4.3) конвертация применяется, когда именующее выражение используется в качестве RValue, но и полоски CV-классификаторов из типов классов в порядке более близко моделировать по значению передачи аргумента. - конец примечание]

Мне кажется, что в идеале std::decay бы модель по значению аргумента проходящее точно, но по какой-то причине она не определена таким образом.

Я думаю, что это можно определить в терминах вывода аргумента шаблона, и в этом случае реализация также может быть определена для вывода аргумента аргумента шаблона в точно прохождение аргумента модели по значению.

template <typename T> 
struct decay { 
    private: 

    template <typename U> 
    static U impl(U); 

    public: 

    using type = decltype(impl(std::declval<T>())); 
}; 

Вопросы:

  1. Каковы различия между std::decay и по значению аргумента мимоходом?
  2. Действительно ли std::decayрассчитан на, чтобы не моделировать аргумент по значению, проходящий точно?
  3. Будет ли реализация выше модели точно?
+3

Одно из отличий заключается в том, что ваша реализация не будет работать, если 'T' не копируется, тогда как' decay' все равно сделает что-то разумное. Следовательно, * models *, но не * is *. – Barry

ответ

7

std::decay был предложен в N2069, мотивирующий пример был std::make_pair вернуть пару decay -ED типов, которая почти как std::make_pair реализован в C++ 11 (есть небольшое исключение для reference_wrapper). Обратите внимание, что предложение изначально не удаляло cv -qualifiers или ссылку на верхний уровень - я предполагаю, что это просто недосмотр.

Что касается причины это просто модели по значению аргумента, проходящей вместо дублирует это, я могу только догадываться, что это может быть, что последняя является слишком ограничительным. Рассмотрим:

struct A { 
    A(const A&) = delete; 
}; 

using T1 = std::decay<A>::type; // T1 == A 
using T2 = your_decay<A>::type; // compile error 
           // use of deleted function A(const A&) 

Я не могу говорить о том, был ли он явно указано таким образом, чтобы обеспечить decay -ную noncopyable типов - но это, кажется, лучший дизайн, чтобы позволить этому компилировать.

+0

В случаях, когда вышеуказанная реализация и компиляция 'std :: decay' (без ранних или поздних ошибок), могут ли они когда-либо возвращать другой тип? Или это 'std :: decay' строгое расширение? – Yakk

+1

@Yakk Я считаю, что это строгое расширение. – Barry

Смежные вопросы