Обходной путь для невыводимого контекста
Рассмотрим следующий код:
#include <iostream>
template<class T>
struct outer {
struct inner {};
};
template<class T>
std::ostream& operator<<(std::ostream & stream,
typename outer<T>::inner const& value) {
std::cout << "An outer::inner!";
return stream;
}
int main() {
outer<float>::inner foo;
std::cout << foo << std::endl; // does not compile
}
Это не скомпилируется, потому что typename outer<T>::inner
представляет собой неопределенный контекст (как описано here), что означает, что тип шаблона-аргумента не может быть выведен компилятор (прочитайте этот ответ, почему). Как я вижу, у меня есть два варианта, чтобы заставить его работать:
- Переместите
inner
вне outer
и сделайте его шаблоном класса. Я предпочитаю это, потому что влияние на код использования меньше.
- Добавьте метод
to_string
к внутреннему.
Есть ли другие решения для этого (которые не приводят к уродливому синтаксису в используемом коде)?
Ответы
Ответ 1
Вы можете переместить оператор во внутреннее тело класса и поставить перед ним friend
. Затем замените тип параметра просто inner
.
Другая методика состоит в том, чтобы вывести внутреннее из базы CRTP, параметризованной внутренним. Затем введите тип параметра CRTP-класс и передайте ссылку параметра на производный класс inner
, тип которого задается аргументом шаблона, который вы выводите.