您的原始代码
以下在 Visual C++ Express 2010 上编译但生成错误答案:
#include <iostream>
template <typename X>
struct point
{
template <typename Seq>
struct point_iterator
{
template <typename>
struct deref
{
static const int value = 0;
};
template <typename Sq>
struct deref< point_iterator<Sq> >
{
static const int value = 1;
};
};
};
int main()
{
typedef point<int> point_t;
typedef point_t::point_iterator<point_t> Iterator;
int v = Iterator::deref<Iterator>::value;
std::cout << v << "\n"; // prints 1 on gcc 4.5.1, prints 0 on VC++ 2010
return 0;
}
这解释了你得到的编译错误:VC++ 试图实例化deref
你没有定义的主模板。在这一点上,看起来 VC++ 是错误的,而 gcc / clang 是优秀的编译器。
中间“解决方案”
但是,将point_iterator
及其嵌套移动deref
到外部命名空间detail
会为 gcc 和 VC++ 提供相同但错误的结果。调用detail::point_iterator::deref
给出了你想要的,但是现在调用嵌套的point_iterator
内部point
会为 gcc 和 VC++ 提供错误的结果!显然,嵌套模板通常对编译器来说很难。
#include <iostream>
namespace detail {
template <typename Seq>
struct point_iterator
{
template <typename>
struct deref
{
static const int value = 0;
};
template <typename Sq>
struct deref< point_iterator<Sq> >
{
static const int value = 1;
};
};
}
template<typename X>
struct point
{
template<typename Seq>
struct point_iterator
:
public detail::point_iterator<Seq>
{};
};
int main()
{
typedef point<int> point_t;
typedef point_t::point_iterator<point_t> Iterator1;
int v1 = Iterator1::deref<Iterator1>::value;
std::cout << v1 << "\n"; // prints 0 on both gcc 4.5.1 and VC++ 2010
typedef detail::point_iterator<point_t> Iterator2;
int v2 = Iterator2::deref<Iterator2>::value;
std::cout << v2 << "\n"; // prints 1 on both gcc 4.5.1 and VC++ 2010
return 0;
}
推荐的方法
嵌套模板还有其他问题:如果不专门化外部模板,就不能明确专门化内部模板(具有讽刺意味的是,VC++ 确实允许这种非标准功能!)。这可以通过使用虚拟模板参数并部分专门化它们来解决(尽管如果您给这个虚拟模板参数一个默认值,VC++ 将需要抑制虚假的编译器警告)。
因此,我的建议是解开您获得的整个嵌套模板层次结构,并简单地定义 3 个单独的模板,并根据您的喜好对它们进行专门化。这将产生最简单的代码并且不会产生任何意外。
#include <iostream>
template<typename X>
struct point {};
template <typename Seq>
struct point_iterator {};
template <typename>
struct deref
{
static const int value = 0;
};
template <typename Sq>
struct deref< point_iterator<Sq> >
{
static const int value = 1;
};
int main()
{
typedef point<int> point_t;
typedef point_iterator<point_t> Iterator1;
int v = deref<Iterator1>::value;
std::cout << v << "\n"; // prints 1 on both gcc 4.5.1 and VC++ 2010
return 0;
}