использование nested-типов шаблона-класса в качестве параметра шаблона

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

Я только что прочитал Вот что лучше реализовать operator << как функция, не являющаяся и не являющаяся другом. Поэтому я решил переместить функции toStream() а также tableToStream() вне MyClass:

template <typename T>
class MyClass
{
public:
typedef boost::dynamic_bitset<> BoolTable;
typedef std::vector<T>          MsgTable;
private:
BoolTable  b_;
MsgTable   m_;
public:
const BoolTable& getB() const { return b_; }
const MsgTable & getM() const { return m_; }

std::ostream& toStream (std::ostream& os) const
{
os <<"Bool: ";  tableToStream (os, getB());  os <<'\n';
os <<"Msg:";    tableToStream (os, getM());  os <<'\n';
return os;
}

template <typename TABLE>
std::ostream& tableToStream (std::ostream& os, const TABLE& table) const
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
};

template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T> mc)
{
return mc.toStream(os);
}

Это легко конвертировать MyClass::toStream() в operator << функция не-член и не-друг:

template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: ";  mc.tableToStream (os, mc.getB());  os <<'\n';
os <<"Msg:";    mc.tableToStream (os, mc.getM());  os <<'\n';
return os;
}

Но я хочу использовать исключительно operator << вместо звонка MyClass::tableToStream():

template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "<< mc.getB() <<'\n';
os <<"Msg:"  << mc.getM() <<'\n';
return os;
}

Для функции MyClass::tableToStream() Я мог бы использовать следующую реализацию, но это может испортить вывод потока, потому что функция слишком общая (любой тип может быть TABLE).

template <typename TABLE>
std::ostream& operator << (std::ostream& os, const TABLE& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}

Поэтому я хочу ограничиться вложенные типы из MyClass, Ниже приведена одна из моих попыток конвертировать MyClass::tableToStream() в стандарт operator << функция не-член и не-друг:

template <typename T, typename MyClass<T>::TABLE>
std::ostream& operator << (std::ostream& os, const TABLE& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}

Но ошибка о typename MyClass<T>::TABLE,

2

Решение

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

Обновленный ответ:
Вы хотите ограничить использование шаблона только теми типами, которые определены в вашем шаблоне MyClass. Такие ограничения обычно достигаются путем применения SFINAE, особенно путем std::enable_if (или же boost::enable_if, если вашей библиотеке не хватает этой части поддержки C ++ 11). К сожалению, нет таких черт, как is_typedeffed_inside это может быть использовано для вашего случая. Еще хуже: нет способа написать такую ​​черту, просто используя простые определения типов, поскольку нет ничего особенного в том, чтобы определить тип внутри определенного класса — компилятор не может определить (и не заинтересован), является ли данный известный Тип имеет псевдоним для него где-то.

Но если ваши typedefs — это те, которые вы показываете в своем вопросе, у меня для вас хорошие новости: вам нужно ровно два operator<< для этого:

  1. Один для boost::dynamic_bitset<>, так как это BoolTable для любой Создание экземпляров MyClass.
  2. Еще один, шаблонный, для std::vector<T>, так как это MsgTable для каждого соответствующего MyClass<T>,

Недостатком является то, что с этим operator<<, вы сможете вывести любой std::vector<FooBar>, даже если FooBar совершенно не связано с любым использованием MyClass. Но это относится к любой другой возможной реализации надлежащего operator<<s — если нет явного ограничения на параметр MSG, нет ограничения на создание FooBar std::vector<FooBar> жизнеспособный MyClass<MSG>::MsgTable,

Мой вывод на ваш вопрос: вы хотели иметь operator<< для его удобного взгляда, так как он обычно используется для этих целей. В вашем случае вы можете предоставить его для MyClass<MSG> объекты, но нет никакого способа сделать это только для внутренних typedefs.

Я бы реализовал это так:

template <class MSG>
class MyClass {
/* ... */
public:
// instead of declaring op<< a friend, redirect to a method that has
// natural access to private members
std::ostream& printToStream(std::ostream& os) const
{
os << "Bool: ";
tableToStream (getB(), os);
os <<"\nMsg:";
tableToStream (getM(), os);
return os <<'\n';
}
private:
// make this one private so nobody can misuse it to print unrelated stuff
template <class Table>
static void tableToStream(Table const& table, std::ostream& os)
{
std::copy(begin(table), end(table), ostream_iterator(os, ", "));
}
};

template <typename MSG>
std::ostream& operator << (std::ostream& os, const MyClass<MSG>& mc)
{
return mc.printToStream(os);
}
1

Другие решения

Ваш оригинальный класс в порядке. Это правда, что если вы хотите иметь operator << для записи в поток, что это должна быть функция, не являющаяся членом, не являющаяся другом, как у вас, но нет причины, по которой функция не может вызывать открытую функцию-член для выполнения работы.

1

Я наконец нашел этот похожий вопрос

В моем случае решение является:

template <typename T>
std::ostream& operator << (std::ostream& os,
typename MyClass<T>::TABLE const& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}

ОБНОВИТЬ: Как указал @ArneMertz, вышеуказанная функция не работает.
Ниже приведен полный код, который я протестировал:

#include <ostream>
#include <boost/dynamic_bitset.hpp>

template <typename T>
class MyClass
{
public:
typedef boost::dynamic_bitset<> BoolTable;
typedef std::vector<T>          MsgTable;

BoolTable  b_;
MsgTable   m_;

const BoolTable& getB() const { return b_; }
const MsgTable & getM() const { return m_; }
};

template <typename T>
std::ostream& operator << (std::ostream& os,
typename MyClass<T>::TABLE const& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}

template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "<< mc.getB() <<'\n'; // <-- this line is OK because it
os <<"Msg:  "<< mc.getM() <<'\n';            //uses boost operator<<
return os;
}

и main функция:

#include <iostream>

int main()
{
MyClass<int> var;
var.b_.push_back(true);
var.b_.push_back(false);
var.b_.push_back(true);
var.m_.push_back(23);
var.m_.push_back(24);
var.m_.push_back(25);

std::cout << var;
}
0

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

template <typename OS, typename MSG, typename MSGTable>
OS& operator << (OS& os, const MSGTable& table) const{}

а затем использовать его как объект.

Увидеть Вот.

-1
По вопросам рекламы [email protected]