Подтвердить что ты не робот

Обходной путь для невыводимого контекста

Рассмотрим следующий код:

#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 к внутреннему.

Есть ли другие решения для этого (которые не приводят к уродливому синтаксису в используемом коде)?

4b9b3361

Ответ 1

Вы можете переместить оператор во внутреннее тело класса и поставить перед ним friend. Затем замените тип параметра просто inner.

Другая методика состоит в том, чтобы вывести внутреннее из базы CRTP, параметризованной внутренним. Затем введите тип параметра CRTP-класс и передайте ссылку параметра на производный класс inner, тип которого задается аргументом шаблона, который вы выводите.