以下代码使用GCC 4.7和clang 3.0编译,但不与MSVC 10编译:
template <typename X>
struct point
{
template <typename Seq>
struct point_iterator
{
template <typename T>
struct deref;
template <typename Sq>
struct deref<point_iterator<Sq> >
{
};
};
};
int main()
{
typedef point<int> point_t;
typedef point_t::point_iterator<point_t> Iterator;
Iterator::deref<Iterator> m;
}
MSVC提供的编译器错误是:
test.cpp
testcpp(21) : error C2079: 'm' uses undefined struct 'point<X>::point_iterator<Seq>::deref<T>'
with
[
X=int,
Seq=point_t
]
and
[
T=Iterator
]
我认为应该定义相关类型,因为它应该匹配deref
的部分特化。
答案 0 :(得分:0)
问题是MSVC10不同意您专门使用该类。如果你试试这个
template <typename Sq>
struct deref
{
typedef int basic;
};
template <typename Sq>
struct deref<point_iterator<Sq> >
{
typedef int special;
};
您会发现Iterator::deref<Iterator>::special
与gcc一起存在,但只有MS存在basic
。
我认为你的代码是正确的。
似乎只有部分专业化受到影响。专注于int
按预期工作。
答案 1 :(得分:0)
您的原始代码
以下在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;
}