Обходной путь для вывода аргумента шаблона в не выводимом контексте - PullRequest
15 голосов
/ 29 ноября 2011

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

#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 представляет собой не выводимый контекст (как описано здесь ), что означаетшаблон-аргумент-тип не может быть выведен компилятором (прочитайте этот ответ для причины).На мой взгляд, у меня есть два варианта, чтобы заставить его работать:

  1. Переместить inner за пределы outer и сделать его шаблоном класса.Я предпочитаю этот, потому что влияние на использование кода меньше.
  2. Добавьте to_string -метод к внутреннему.

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

1 Ответ

22 голосов
/ 29 ноября 2011

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

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

...