/ / Przekazywanie referencji i szablonów szablonów - c ++, c ++ 11, szablony szablonów, funkcja szablonów, przekazywanie referencji

Przekazywanie referencji i szablonów szablonów - c ++, c ++ 11, szablony szablonów, funkcje szablonu, przekazywanie-referencje

Rozważ te dwie funkcje szablonu:

template<typename T>
void foo(T&& bar) {
// do stuff with bar, which may or may not be an instance of a templated class
}

template<typename U, template<typename> class T>
void foo(T<U>&& bar) {
// do stuff with bar, which must be an instance of a templated class
}

Dlaczego te pierwsze akceptują wartości lv (przy użyciu referencji przekazywania), a te drugie nie?


To wygląda jak Czy szablon aliasu tożsamości może być referencją przekazywania? może być również z tym związany, ale wydaje się, że obejmuje on inny aspekt ograniczeń dotyczących przekazywania referencji.

Odpowiedzi:

2 dla odpowiedzi № 1

Ponieważ tak mówi standard, że język powinien działać.

[14.8.2.1] [temp.deduct.call]
3.Jeśli P jest typem kwalifikowanym do CV, kwalifikatory najwyższego poziomu typu P są ignorowane w celu odliczenia typu. Jeśli P jest a typ odniesienia, typ określony przez P służy do odliczenia typu. ZA przekazanie przekierowania to wartość odwołanie do parametru szablonu niekwalifikowanego cv. Jeśli P jest odwołaniem do przekazywania, a argumentem jest lvalue, typ „lvalue reference to A” jest używany zamiast A do odliczenia typu.

W ten sposób można wydedukować jedynie odniesienie do wartości do parametru szablonu niekwalifikowanego jako odniesienie wartości l.

Aby osiągnąć to, co próbujesz zrobić, możesz użyć cechy do wyodrębnienia parametru szablonu szablonu.

#include <type_traits>

/***
* Extract template from template type.
*/
template <typename I> struct get_template;

template <template<class> typename T, typename C>
struct get_template<T<C>> {
template <typename U>
using temp = T<U>;
};





template <typename T> struct A{};

struct B;

template<typename W>
void foo(W && bar) {
typedef typename get_template<typename std::remove_reference<W>::type>::template temp<int> new_type;
new_type my_variable;
}

int main() {
A<B> temp;
foo(temp);
}

Lub po prostu przeciąż funkcję dla const & i && jak zwykle.


3 dla odpowiedzi № 2

Jeśli chcesz zachować parametr referencyjny przekazywania, a jednocześnie wydedukować typ argumentu, możesz użyć poniższego rozwiązania:

#include <type_traits>
#include <utility>

template <typename T>
struct tag {};

template <typename T, typename U, template <typename> class C>
void foo(T&& t, tag<C<U>>)
{

}

template <typename T>
auto foo(T&& t)
-> decltype(foo(std::forward<T>(t), tag<typename std::decay<T>::type>{}))
{
return foo(std::forward<T>(t), tag<typename std::decay<T>::type>{});
}

PRÓBNY