【发布时间】:2015-08-03 02:04:53
【问题描述】:
我有一个指向类模板实例(例如 Counter)的非类型类模板(例如 Counted)。只要两个模板类是兄弟,一切都可以正常工作,例如编写打印运算符。
现在出于几个原因,我想将 Counted 作为内部类移动到 Counter 中,但我发现自己无法编写打印运算符。
Here's a working "sibling class" version,主要代码在这里:
template < class Count >
struct Counter {
using count_type = Count;
count_type instances = 0;
};
template < class Cnt, Cnt& c>
struct Counted {
using id_type = typename Cnt::count_type;
id_type id;
Counted() : id(c.instances) { ++c.instances; }
~Counted() { --c.instances; }
};
template < class Cnt, Cnt& c >
std::ostream& operator<<(std::ostream& os, Counted<Cnt,c> sib) {
os << "printing sibling " << sib.id;
return os;
}
using SCounter = Counter<std::size_t>;
SCounter sc;
using SCounted = Counted<SCounter, sc>;
Here's the not compiling "inner class" version 这里有主要代码:
template < class Count >
struct Counter {
using count_type = Count;
count_type instances = 0;
template <Counter& c>
struct Counted {
using id_type = count_type;
id_type id;
Counted() : id(c.instances) { ++c.instances; }
~Counted() { --c.instances; }
};
};
template < class Count, Counter<Count>& c >
std::ostream& operator<<(std::ostream& os,
typename Counter<Count>::template Counted<c>& sib) {
os << "printing inner " << sib.id;
return os;
}
using SCounter = Counter<std::size_t>;
SCounter sc;
using SCounted = SCounter::Counted<sc>;
错误:
prog.cpp: In function 'int main()':
prog.cpp:32:15: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << j << std::endl;
^
In file included from /usr/include/c++/4.9/iostream:39:0,
from prog.cpp:1:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Counter<unsigned int>::Counted<(* & sc)>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
我的代码、我的编译器是否有问题,还是标准不允许这样做?
【问题讨论】:
-
在您的
operator<<中,typename Counter<Count>::中的Count位于非推断上下文 中。也就是说,编译器无法从函数参数中推断出它。您可以使operator<<更通用 - 如template<class C> std::ostream& operator<<(std::ostream&, C const&)- 然后限制它,例如通过 SFINAE。 -
在
Counted类模板中将operator<<定义为非成员朋友函数更容易。 -
此外,[temp.deduct.type]p13 “不能从非类型模板参数的类型推导出模板类型参数。”所以
template<class C, Counter<C>& r, template<Counter<C>&> class T> ostream& operator<<(ostream&, T<r> const&);也是不允许的,因为C可能不能从r推导出来。 -
感谢 dyp,与
operator<<成为朋友正是我想要的。我应该考虑到这一点。也感谢您的解释。
标签: c++ c++11 type-inference