我在编译以下代码时遇到问题,它只会导致编译错误,见下文。
我不明白的是:
如果我的类Any
本身不是模板类,则所有类都按预期工作。 (您可以将示例代码行取消注释到此。
如果Any
是模板,则BASE_T
不再可见。有没有让它再次可见的技巧?
为什么我需要BASE_T
?如您所见,ConcatHelper模板从所有类型创建一个类,该类是此模板的可变参数列表的一部分。真实世界的代码做了更多,但这里的例子并不重要。我定义了BASE_T
以减少我的代码,并且不能一次又一次地复制所有模板参数。
使用过的编译器:g ++ 5.3.1和gcc6的最新快照。
#include <iostream>
class F {};
template<typename T>
class FReader
{
public:
FReader(F&){}
};
template<typename T> class A { };
template<typename T> class B { };
template < typename FILETYPE, typename Base, typename ...Tail> class ConcatHelper;
template <typename FILETYPE, typename Base, typename Head, typename ...Tail>
class ConcatHelper< FILETYPE, Base, Head, Tail...>: public Head, public ConcatHelper< FILETYPE, Base, Tail... >
{
public:
typedef ConcatHelper< FILETYPE, Base, Head, Tail...> BASES_T;
ConcatHelper(FILETYPE &_is): ConcatHelper< FILETYPE, Base, Tail... >(_is){}
};
template<typename FILETYPE, typename Base>
class ConcatHelper<FILETYPE, Base>: public Base
{
public:
ConcatHelper(FILETYPE& _i): Base(_i){}
};
//class OUTER_MASTER{};
template <typename OUTER_MASTER>
class Any: public ConcatHelper<F, FReader<OUTER_MASTER>, A<OUTER_MASTER>,B<OUTER_MASTER>>
{
public:
Any( F& is): BASES_T ( is ) {} // did not compile
//Any( F& is):ConcatHelper<F, FReader<OUTER_MASTER>, A<OUTER_MASTER>,B<OUTER_MASTER>>(is) {} // compiles
};
int main()
{
F f;
Any<int> gr(f);
//Any gr(f);
}
结果:
error: class 'Any<OUTER_MASTER>' does not have any field named 'BASES_T'
如果我改变:
Any( F& is): BASES_T ( is ) {}
到
Any( F& is): std::remove_reference<decltype(*this)>::type::BASES_T ( is ) {}
但这是非常有效的c ++代码吗?
答案 0 :(得分:4)
要使用模板派生类中的typename,您需要限定使用的类型名称。
正如C ++标准所说(14.6.2 / 3):
在类模板的定义或类模板的成员中, 如果类模板的基类依赖于模板参数, 在非限定名称查找期间不检查基类范围 无论是在类模板或成员的定义点还是 在类模板或成员的实例化过程中。
使用类名限定构造函数有效:
template <typename OUTER_MASTER>
class Any: public ConcatHelper<F, FReader<OUTER_MASTER>, A<OUTER_MASTER>,B<OUTER_MASTER>>
{
public:
Any( F& is): Any::BASES_T(is) {}
};