当内部类使用外部类的template参数时,我会遇到编译器错误,并且我在内部类型的成员的外部类上实例化了一个输出流运算符。
我花了很多时间尝试解决此问题。我相信以下资料来源接近,但我仍然不明白为什么我编译失败。
这是代码:
#include <iostream>
#include <vector>
template <typename T>
struct Outer
{
struct Inner
{
Inner(const T& val = T());
T data_;
}; // end class Inner
Outer();
void AddInnerChildToOuter(const T& data);
std::vector<typename Outer<T>::Inner> innerChildren_;
}; // end class Outer
// Inner constructor
template <typename T>
Outer<T>::Inner::Inner(const T& val) : data_(val)
{
}
template <typename T>
std::ostream& operator<<(std::ostream& strm, // Line 27
const typename Outer<T>::Inner& gn)
{
strm << gn.data_ << std::endl;
return strm;
}
// Outer constructor
template <typename T>
Outer<T>::Outer()
{
}
template <typename T>
void Outer<T>::AddInnerChildToOuter(const T& data)
{
typename Outer<T>::Inner node(data);
innerChildren_.push_back(node);
}
template <typename T>
std::ostream& operator<<(std::ostream& strm, const Outer<T>& g)
{
for (size_t i = 0; i < g.innerChildren_.size(); ++i)
std::cout << g.innerChildren_[i] << std::endl; // Line 51
return strm;
}
int main()
{
Outer<int> g;
g.AddInnerChildToOuter(3);
g.AddInnerChildToOuter(5);
std::cout << g << std::endl; // Line 60
return 0;
}
我在外部得到ostream operator <<
的编译器错误,该错误为内部调用了相应的输出流运算符。我没有发布编译器错误消息的全部内容;我认为是相关的。$ g++ -Wall -W -Wextra -pedantic -ansi OuterInnerArgh.cpp
OuterInnerArgh.cpp: In instantiation of ‘std::ostream& operator<<(std::ostream&, const Outer<T>&) [with T = int; std::ostream = std::basic_ostream<char>]’:
OuterInnerArgh.cpp:60:18: required from here
OuterInnerArgh.cpp:51:19: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘const Outer<int>::Inner’)
std::cout << g.innerChildren_[i] << std::endl;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
(扼杀了编译器在各种ostream
重载中的尝试;下面有更多编译器错误消息)OuterInnerArgh.cpp:27:15: note: candidate: template<class T> std::ostream& operator<<(std::ostream&, const typename Outer<T>::Inner&)
std::ostream& operator<<(std::ostream& strm,
^~~~~~~~
OuterInnerArgh.cpp:27:15: note: template argument deduction/substitution failed:
OuterInnerArgh.cpp:51:19: note: couldn't deduce template parameter ‘T’
std::cout << g.innerChildren_[i] << std::endl;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
OuterInnerArgh.cpp:48:15: note: candidate: template<class T> std::ostream& operator<<(std::ostream&, const Outer<T>&)
std::ostream& operator<<(std::ostream& strm, const Outer<T>& g)
^~~~~~~~
OuterInnerArgh.cpp:48:15: note: template argument deduction/substitution failed:
OuterInnerArgh.cpp:51:19: note: ‘const Outer<int>::Inner’ is not derived from ‘const Outer<T>’
std::cout << g.innerChildren_[i] << std::endl;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
(其余的编译器错误已删除)请让我知道为什么遇到编译器错误-
ostream operator <<
的typename Outer<T>::Inner&
typename
“magic-dust”ostream
运算符,不适用于构造函数或内部ostream
运算符(后者可能根本没有实例化?)为什么编译器说
‘const Outer<int>::Inner’ is not derived from ‘const Outer<T>’
? (是的,没有继承,但是内部类型定义嵌套在外部内部)
最佳答案
由于non-deduced context导致模板参数推导失败,因此出现编译错误。
In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
- The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a qualified-id:
例如,如果您明确指定模板参数(丑陋的风格),它将进行编译。在
operator<<
的Outer
中:operator<< <T> (strm, g.innerChildren_[i]);
// ^^^
您可以将operator<<
设置为非模板(以绕过类型推导的麻烦),然后必须在类定义中将其定义为friend
。例如struct Inner
{
Inner(const T& val = T());
T data_;
friend std::ostream& operator<<(std::ostream& strm,
const Inner& gn)
{
strm << gn.data_ << std::endl;
return strm;
}
};
LIVE
关于c++ - 内部类使用外部类模板参数时(仅当使用 `ostream`时)编译失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62731057/