任何人都可以解释为什么以下代码无法编译:
template <typename P>
struct Base
{
friend typename P::One;
friend typename P::Two;
friend typename P::Three;
};
template<typename U, typename D, typename T>
struct Derived : public Base<Derived<U,D,T>>
{
using One = U;
using Two = D;
using Three = T;
};
错误是:
..\PRP\main.cpp:3:1: error: no type named 'One' in 'struct Derived<A, B, C>'
{
^
..\PRP\main.cpp:3:1: error: no type named 'Two' in 'struct Derived<A, B, C>'
..\PRP\main.cpp:3:1: error: no type named 'Three' in 'struct Derived<A, B, C>'
为什么下面的代码编译得很完美:
template <typename T>
struct Sum
{
constexpr static int sze = T::uno + T::due + T::tre;
};
template<int i, int j, int k>
struct Triple : public Sum<Triple<i, j, k>>
{
constexpr static int uno = i;
constexpr static int due = j;
constexpr static int tre = k;
};
两者有什么区别?我认为这与模板演绎顺序有关,但我可能错了。
我在Win7上使用带有标志C ++ 11的MinGW 4.8。 谢谢!
答案 0 :(得分:8)
您的代码中没有发生模板参数推断,因此这与推理没有任何关系。
问题是由Derived
成员使用Base<Derived<U,D,T>>
时不完整而导致的。
编译器在Derived
的实例化过程中会立即处理好友声明,这些声明出现在Derived
的基类列表中,并且此时Sum
不完整,因此尝试使用其成员是不可能的。
Triple
中的静态成员未自动实例化,并且在Triple
的声明中不需要。如果您稍后使用静态成员,则Sum<T>::sze
是完整类型,并且可以引用其成员。
如果您尝试在Sum
的定义中使用T
,则会收到类似的错误,因为此时template <typename T>
struct Sum
{
constexpr static int sze = T::uno + T::due + T::tre;
char buf[sze];
};
template<int i, int j, int k>
struct Triple : public Sum<Triple<i, j, k>>
{
constexpr static int uno = i;
constexpr static int due = j;
constexpr static int tre = k;
};
Triple<1, 2, 3> t;
不是完整类型:
{{1}}