同样的代码可以被clang编译,但在gcc中会失败
The same code gets compiled by clang but fails in gcc
是我还是编译器错了?我试图在gcc下编译这个修复,但找不到方法。错误消息很简单,FactorialTree<T, 0>::print
是私有的,但是为什么clang没有问题地接受它?另外,我如何为gcc修复这个问题?
#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);
}
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);
// ...
}
相关文章:
- std::unique_ptr 在 GCC 中工作,但不能在 Visual Studio 中编译
- 没有'str'成员在 GCC 和 Clang 'std::basic_ostream<char>',但 MSVC 没有问题
- 带有引用的std::tuple在clang中编译失败,但在gcc中编译失败
- 为什么以下代码在在线 ide(gcc 7.2.0) 上有效,但在 ubuntu 上出现错误?
- Boost tread 代码在 VC++ 下编译,但不在 GCC 下编译:如何获得更好的调试信息
- VC 中的运行时错误,但不在GCC中
- enable_if is_same constexpr函数使MSVC失败(但在Clang,GCC中效果很好)
- 为什么一些 GCC 警告标志不属于C++语言,但在C++中工作
- 从std::map派生的类不在Visual C++上编译(但在gcc和clang上编译)
- constexpr(但不是真正的)构造函数在GCC中编译,而不是在Clang中编译
- GCC/Clang上的模板错误,但在MSVC上没有错误
- 带有可变参数的嵌套宏在GCC中编译,但在MSVC中不编译
- 为什么这段代码在Visual Studio中有效,但在gcc中失败
- 作为模板非类型参数的 C 字符串在 gcc 6.3 中有效,但在 Visual Studio 2017(x64 为 19
- gcc linker - .obj dump 具有混合源代码程序集,但在 .elf 中链接时没有
- C++ MSVC 中的访问冲突,但不在 GCC 中进行多重继承和强制转换
- 成员函数模板不会在 clang 上编译,但在 GCC 上编译
- xtables_find_match 中的 g++ 不起作用,但在 gcc 中很好
- 在 clang 中显式指定的参数无效,但在 gcc 中成功编译 — 谁错了?
- 同样的代码可以被clang编译,但在gcc中会失败