模板参数推导顺序
Template argument deduction order
任何人都可以解释为什么以下代码无法编译:
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 上使用 MinGW 4.8,并启用了标志 C++11。
谢谢!
您的代码中没有发生模板参数推导,因此这与推导无关。
问题是由于 Derived
的成员类型不完整而导致的。
在 Derived
的基 class 列表中出现 Base<Derived<U,D,T>>
的实例化期间,编译器会立即处理友元声明,此时 Derived
不完整,因此无法尝试使用其成员。
Sum
中的静态成员不会自动实例化,并且在 Triple
的声明中不需要。如果以后使用静态成员,那么Triple
是一个完整的类型,它的成员可以被引用。
如果你尝试在 Sum
的定义中使用 Sum<T>::sze
你会得到类似的错误,因为 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;
任何人都可以解释为什么以下代码无法编译:
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 上使用 MinGW 4.8,并启用了标志 C++11。 谢谢!
您的代码中没有发生模板参数推导,因此这与推导无关。
问题是由于 Derived
的成员类型不完整而导致的。
在 Derived
的基 class 列表中出现 Base<Derived<U,D,T>>
的实例化期间,编译器会立即处理友元声明,此时 Derived
不完整,因此无法尝试使用其成员。
Sum
中的静态成员不会自动实例化,并且在 Triple
的声明中不需要。如果以后使用静态成员,那么Triple
是一个完整的类型,它的成员可以被引用。
如果你尝试在 Sum
的定义中使用 Sum<T>::sze
你会得到类似的错误,因为 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;