[英]using nested-types of a template-class as template parameter
I want to implement a template function using nested-types of a template-class. 我想使用模板类的嵌套类型来实现模板功能。
I have just read here that it is better to implement operator <<
as non-member and non-friend function. 我刚刚在这里读到,最好将operator <<
实现为非成员和非朋友函数。 Therefore I decided to move functions toStream()
and tableToStream()
outside MyClass
: 因此,我决定将函数toStream()
MyClass
之外的toStream()
和tableToStream()
:
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);
}
It's easy to convert MyClass::toStream()
into an operator <<
non-member and non-friend function: 将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;
}
But I want to use solely operator <<
instead of calling MyClass::tableToStream()
: 但是我只想使用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;
}
For the function MyClass::tableToStream()
I could use the following implementation, but this may mess the stream output because the function is too generic (any type can be TABLE
). 对于函数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;
}
Therefore, I want to restrict to the nested types of MyClass
. 因此,我想限制MyClass
的嵌套类型 。 Below is one of my attempts to convert MyClass::tableToStream()
into a standard operator <<
non-member and non-friend function: 以下是我将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;
}
But the error is about typename MyClass<T>::TABLE
. 但是错误是关于typename MyClass<T>::TABLE
。
Since you have clarified your question a lot, my first answer does not apply any more and I'll remove-edit it to give you something that might fit better: 既然您已经澄清了很多问题,那么我的第一个答案将不再适用,我将对其进行删除-编辑,以便为您提供更好的选择:
Updated answer: You want to constrain the template to accept only types that are typedeffed inside your MyClass template. 更新的答案:您希望将模板限制为仅接受在MyClass模板中键入有效的类型。 Such constraints are usually achieved by application of SFINAE, especially by std::enable_if
(or boost::enable_if
, if your library lacks that part of C++11 support). 通常通过应用SFINAE来实现这种约束,特别是通过std::enable_if
(或boost::enable_if
,如果您的库缺少C ++ 11支持的部分)。 Sadly, there is no traits like a is_typedeffed_inside
that could be used for your case. 可悲的是,没有像is_typedeffed_inside
这样的特征可以用于您的案例。 It's even worse: there is no way to write such a trait just using the plain typedefs, since there is nothing special about being typedeffed inside a given class - the compiler has no way to determine (and is not interested in) if a given known type has some alias name for it somewhere. 更糟糕的是:仅使用普通的typedef就无法编写这样的特征,因为在给定的类中进行类型化没有什么特别的-编译器无法确定(并且不关心)给定的已知值类型在某处具有一些别名。
But if your typedefs are just the ones you show in your question, I have good news for you: you need exactly two operator<<
for that: 但是,如果您的typedef只是您在问题中显示的typedef,那么我对您来说是个好消息:您恰好需要两个operator<<
:
boost::dynamic_bitset<>
, since that is the BoolTable for any MyClass instantiation. 一个用于boost::dynamic_bitset<>
,因为它是任何 MyClass实例化的BoolTable。 std::vector<T>
, since that is the MsgTable for each corresponding MyClass<T>
. 另一个模板化为std::vector<T>
,因为这是每个对应的MyClass<T>
的MsgTable。 The downside is, that with this templated operator<<
, you'd be able to output any std::vector<FooBar>
, even if FooBar
is completely unrelated to any use of MyClass. 缺点是,使用此模板化的operator<<
,即使FooBar
与MyClass的使用完全无关,您也可以输出任何std::vector<FooBar>
。 But that holds for any other possible implementation of the proper operator<<
's - if there's no explicit restriction on the MSG parameter, there's no restriction on a FooBar making a std::vector<FooBar>
a viable MyClass<MSG>::MsgTable
. 但这适用于适当的operator<<
的任何其他可能的实现-如果对MSG参数没有明确限制,则对FooBar也没有限制,使std::vector<FooBar>
成为可行的MyClass<MSG>::MsgTable
My conclusion for your question: you wanted to have the operator<<
for its convenient looks, since it is normally used for thet purpose. 我对您的问题的结论是:您希望使用operator<<
以便于查看,因为通常将其用于此目的。 In your case, you can provide it for MyClass<MSG>
objects, but there is no way to do so for the inner typedefs alone. 在您的情况下,可以为MyClass<MSG>
对象提供它,但是没有办法仅对内部typedef提供它。
I'd implement it that way: 我可以这样实现:
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);
}
Your original class is fine. 你原来的课没问题。 It is true that if you want to have an operator <<
for writing to a stream that it should be a non-member non-friend function, like you have, but there is no reason that function can't call a public member function to do the work. 的确,如果您想要一个operator <<
来写入流,则它应该像您一样是非成员非朋友函数,但是没有理由该函数不能调用公共成员函数做工作。
I finally found this similar question 我终于找到了类似的问题
In my case the solution is: 就我而言, 解决方案是:
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;
}
UPDATE: As @ArneMertz pointed out, the above function does not work. 更新:正如@ArneMertz所指出的,上述功能不起作用。
Below is the complete code I have tested: 以下是我测试过的完整代码:
#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;
}
and the main
function: 和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;
}
I believe you are confusing something. 我相信您会感到困惑。 The typename is just to be able to seperate it from the other template-parameters. 类型名称只是为了能够将其与其他模板参数分开。 Try to rename it to 尝试将其重命名为
template <typename OS, typename MSG, typename MSGTable>
OS& operator << (OS& os, const MSGTable& table) const{}
and then use it like an object. 然后像一个对象一样使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.