我正在查看一些大量使用模板的代码。它在GCC上编译得很好,但在VS(在2003 - 2010 beta 1上测试)上没有编译,在语法分析期间它失败了。不幸的是,我不知道足够的代码结构能够减少问题并只在几行中重现它,所以我只能猜测原因。我希望有人能指出我正确的方向。
我们有
template< class UInt, typename IntT,
bool is_signed = std::numeric_limits<IntT>::is_signed >
struct uii_ops_impl;
// ....
template<class UInt>
struct uii_ops_impl< UInt,
typename make_signed<typename UInt::digit_type>::type, true >
{
typedef UInt unbounded_int_type;
typedef typename make_signed< typename unbounded_int_type::digit_type >::type
integral_type;
// ...
static void add(unbounded_int_type& lhs, integral_type rhs);
// ...
};
template<class UInt>
void uii_ops_impl<
UInt, typename make_signed<typename UInt::digit_type>::type,
true >::add(unbounded_int_type& lhs, integral_type rhs)
{
// ....
}
在VS上编译时,它返回的第一条错误消息(在众多中)是
:错误C2065:'
unbounded_int_type
':未声明的标识符
我的意思是,指向typedef 吧? :-S
修改
似乎与
有关typename make_signed<typename UInt::digit_type>::type
用作模板参数。在其余的代码中,在member function参数中使用的类似typedef编译得很好。到目前为止,我能看到的唯一区别是没有其他情况将上述行作为模板参数。 make_signed
来自Boost.TypeTraits。
修改
好吧,也许那不是它,因为完全相同的事情是在另一个编译好的文件中完成的。嗯...
Bounty编辑:
好的,我认为现在很明显问题实际上并不是编译器所抱怨的问题。只有该特定点的两个成员函数定义失败。事实证明,明确限定参数仍然不编译。唯一的直接解决方案是定义内联函数。这通过了语法分析。但是,在尝试安装模板时,VS现在失败,因为std::allocator<void>
没有size_type
成员。事实证明,对于T = void,VS具有std::allocator<T>
的特化,不会声明size_type
。我以为size_type
是所有分配器的必需成员?
所以现在的问题是,在语法分析过程中可能会对VS造成太大的影响,因为它抱怨完全不相关的非问题是错误,你如何调试这些代码呢?
P.S。对于那些有太多时间闲暇的人来说,我试图在VS中工作的代码是Kevin Sopp在Boost的沙箱中的mp_math,它基于libtommath。
答案 0 :(得分:6)
我认为这可能是由一些情况造成的
unbounded_int_type
是non-dependent
类型(在14.6.2.1
定义)我怀疑Visual C ++无法执行此查找,而是出错。正如其他人提到的那样,您可以在成员函数定义中明确限定类型名称。然后依赖于类型,这将触发编译器的机制以延迟名称查找直到实例化。
template<class UInt>
void uii_ops_impl<
UInt, typename make_signed<typename UInt::digit_type>::type,
true >::add(typename
/* repeat-that-beast uii_ops...true> here */
::unbounded_int_type& lhs,
typename /* and here too */::integral_type rhs)
{
// ....
}
答案 1 :(得分:1)
这是一个有趣的东西 - 这家伙
遇到了与你所看到的非常类似的MSVC的一个错误 - 除了使用一个typedef解决了他的问题。
我仍然不知道他遇到的问题是什么(或者你遇到的问题)。正如您所说,您发布的小代码段不会重现错误(假设make_signed<>
模板允许make_signed<>::type
可编辑)。
答案 2 :(得分:0)
哪一行导致第一个错误?
在此定义中是否使用unbounded_int_type:
template<class UInt>
void uii_ops_impl<
UInt, typename make_signed<typename UInt::digit_type>::type,
true >::add(unbounded_int_type& lhs, integral_type rhs)
{
// ....
}
需要完全合格:
template<class UInt>
void uii_ops_impl<
UInt, typename make_signed<typename UInt::digit_type>::type,
true >::add(uii_ops_impl<UInt, etc ,true>::unbounded_int_type& lhs, integral_type rhs)
{
// ....
}
答案 3 :(得分:0)
你必须在这个上帮助编译器。您必须使用typename
关键字,因为您具有引用类型的限定名称并且取决于模板参数。
请注意,您如何确定unbounded_int_type::digit_type
是一种类型?这取决于unbounded_int_type
的类型。因此,您可以通过添加typename
关键字来消除歧义。
template< class UInt, typename IntT,
bool is_signed = std::numeric_limits<IntT>::is_signed >
struct uii_ops_impl;
// ....
template <class T>
struct make_signed
{
typedef T type;
};
template<class UInt>
struct uii_ops_impl< UInt,
typename make_signed<typename UInt::digit_type>::type, true >
{
typedef UInt unbounded_int_type;
typedef typename make_signed< typename unbounded_int_type::digit_type >::type
integral_type;
// ...
static void add(unbounded_int_type& lhs, integral_type rhs);
// ...
};
template<class UInt>
void uii_ops_impl<
UInt, typename make_signed<typename UInt::digit_type>::type,
true >::add(unbounded_int_type& lhs, integral_type rhs)
{
// ....
}
唯一的变化就在这里 - 我添加了typename
关键字。
typedef typename make_signed< typename unbounded_int_type::digit_type >::type integral_type;