是我还是编译器错了?我试图修复以在gcc下编译但无法找到方法。错误信息非常简单,FactorialTree<T, 0>::print
是私有的,但是为什么clang接受它没有问题?另外,我如何解决这个问题呢?
#include <ostream>
#include <cstring>
template<typename T, std::size_t nChildren>
class FactorialTreeBase
{
protected:
FactorialTreeBase<T, nChildren + 1> *parent;
public:
T data;
FactorialTreeBase(FactorialTreeBase<T, nChildren + 1> *p, const T &t)
: parent(p)
, data(t)
{
}
const FactorialTreeBase<T, nChildren + 1> *getParent() const
{
return parent;
}
FactorialTreeBase<T, nChildren + 1> *getParent()
{
return parent;
}
protected:
static void printIndents(std::ostream &os, std::size_t nIndents)
{
for (std::size_t i = 0; i < nIndents; ++i)
{
os << " ";
}
os << "+-";
}
};
template<typename T, std::size_t nChildren>
class FactorialTree
: public FactorialTreeBase<T, nChildren>
{
friend class FactorialTree<T, nChildren + 1>;
public:
FactorialTree<T, nChildren - 1> *children[nChildren];
FactorialTree(FactorialTree<T, nChildren + 1> *p = nullptr, const T &t = T())
: FactorialTreeBase<T, nChildren>(p, t)
{
std::memset(children, 0, nChildren * sizeof *children);
}
FactorialTree(const FactorialTree<T, nChildren> &) = delete;
FactorialTree<T, nChildren> &operator=(const FactorialTree<T, nChildren> &) = delete;
FactorialTree(FactorialTree<T, nChildren> &&) = delete;
FactorialTree<T, nChildren> &operator=(FactorialTree<T, nChildren> &&) = delete;
~FactorialTree()
{
for (std::size_t i = 0; i < nChildren; ++i)
{
if (children[i])
{
delete children[i];
}
}
}
friend std::ostream &operator<<(std::ostream &os, const FactorialTree<T, nChildren> &ft)
{
for (std::size_t i = 0; i < nChildren; ++i)
{
if (ft.children[i])
{
ft.children[i]->print(os, 0);
}
}
return os;
}
private:
void print(std::ostream &os, std::size_t nIndents) const
{
this->printIndents(os, nIndents);
os << this->data << '\n';
for (std::size_t i = 0; i < nChildren; ++i)
{
if (children[i])
{
children[i]->print(os, nIndents + 1);
}
}
}
};
template<typename T>
class FactorialTree<T, 0>
: public FactorialTreeBase<T, 0>
{
friend class FactorialTree<T, 1>;
public:
FactorialTree(FactorialTree<T, 1> *p = nullptr, const T &t = T())
: FactorialTreeBase<T, 0>(p, t)
{
}
private:
void print(std::ostream &os, std::size_t nIndents) const
{
this->printIndents(os, nIndents);
os << this->data << '\n';
}
};
#include <iostream>
enum
{
N = 3
};
template<std::size_t n>
void fillTree(FactorialTree<int, n> *ft)
{
for (std::size_t i = 0; i < n; ++i)
{
ft->children[i] = new FactorialTree<int, n - 1>;
ft->children[i]->data = i;
fillTree(ft->children[i]);
}
}
template<>
void fillTree(FactorialTree<int, 0> *)
{
}
template<std::size_t n>
void printAndCutTree(FactorialTree<int, n> *ft)
{
std::cout << *ft << '\n';
for (std::size_t i = 1; i < n; ++i)
{
delete ft->children[i];
ft->children[i] = nullptr;
}
printAndCutTree(ft->children[0]);
}
template<>
void printAndCutTree(FactorialTree<int, 0> *)
{
}
int main()
{
FactorialTree<int, N> t;
fillTree(&t);
printAndCutTree(&t);
}
答案 0 :(得分:3)
Clang不应该编译这个。 FactorialTree<T, 0>
是一种专业化,在其中您不会确认operator<<
的友谊。专业化不与通用案例共享代码,因此您的operator<<
无法看到专业化的私有字段。对此的一个解决方案是使operator<<
成为一个模板,然后将其专门化并使其成为FactorialTree<T, nChildren>
和FactorialTree<T, 0>
中的朋友:
// forward declaration of the FactorialTree
template<typename T, std::size_t nChildren>
class FactorialTree;
// operator<< is now a template, rather than an overload
template<typename T, std::size_t nChildren>
std::ostream &operator<<(std::ostream &os, const FactorialTree<T, nChildren> &ft)
{
for (std::size_t i = 0; i < nChildren; ++i)
{
if (ft.children[i])
{
ft.children[i]->print(os, 0);
}
}
return os;
}
// the generic case
template<typename T, std::size_t nChildren>
class FactorialTree
: public FactorialTreeBase<T, nChildren>
{
friend class FactorialTree<T, nChildren + 1>;
// specialising operator<< and making it a friend:
friend std::ostream &operator<< <>(std::ostream &os, const FactorialTree<T, nChildren+1> &ft);
// ...
}
// the specialisation
template<typename T>
class FactorialTree<T, 0>
: public FactorialTreeBase<T, 0>
{
friend class FactorialTree<T, 1>;
// again, specialising operator<< and making it a friend
friend std::ostream &operator<< <>(std::ostream &os, const FactorialTree<T, 1> &ft);
// ...
}