2012-10-06 86 views
6

不知何故,我喜欢这些“最短”的程序显示(基本?)问题。当在VS2008中测试一些模板代码时,这个错误出现了(它也被VS2010和VS2012证实,见下文):STL的VS编译器错误C2752(“多个部分专业化匹配”)

c:\ program files(x86)\ microsoft visual studio 9.0 \ vc \ include \ xmemory(225):错误C2752: '的std :: _ Ptr_cat_helper < _T1,_T2>':一个以上的部分特化的模板参数列表

with 
    [ 
     _T1=const float (**), 
     _T2=const float (**) 
    ] 

我可以归结问题有以下三个行相匹配:

#include <vector> 
typedef float TPoint[3]; 
std::vector<TPoint const*> points; // error C2752 

注意,以下是一切ok

#include <vector> 
#include <list> 
typedef float TPoint[3]; 
// these similar usages of TPoint are all ok: 
std::vector<TPoint*> points; // no error 
TPoint const* points1[2]; 
std::list<TPoint const*> points2; 

我试图通过结构_Ptr_cat_helper提供额外的模板spezializations修复xutility - 没有运气。任何想法出了什么问题?或者如何解决而不会丢失const

+1

还没有安装VS在我面前,但它与海湾合作委员会的工作。您可能在标准库中找到了一个错误。 –

+0

升级VS目前是不可能的:我们依赖于来自其他团队的dll(使用MFC组件)......但是,如果上面的三行代码在VS2010上编译将会很好听 – coproc

+0

对不起,它不能编译,这就是为什么我删除了该评论。 :尽管这个矢量的元素应该是什么,但这并不完全清楚。一个指向三个const Float元素的数组的指针? – Xeo

回答

8

问题是确实是在一个部分特歧义:

在内部,该分配器使用一些元编程(_Ptr_cat),以确定是否析构函数是对矢量的元素将被称为(或什么也不做)。这个元编程试图通过使用部分专业化来区分某些情况。 _Ptr_cat使用_Ptr_cat_helper这是专门用于矢量的分配器的指针类型 - 矢量的value_typeTPointer const* == const float (*)[3],所以该矢量的分配器有一个指针类型const float(**)[3]

当使用std::vector < const float(*)[3] >,错误消息包含[3]部分,而使用std::vector < TPoint const* >,所述[3]不显示o.O

_Ptr_cat预计两个相同类型的模板参数具有可能不同的c-限定符,例如float*, float const*。 现在,这两种输入类型都是const float (**)[3]。 MSVC不明确地将其解决为_Ptr_cat_helperTy**, Ty const**和/或Ty**, Ty**的专业化。我通过编写一个模仿_Ptr_cat_helper(只是普通模板,不涉及Std Lib)的部分专业化的小例子来验证。

但是,我无法解释为什么会发生这种情况。奇怪的是,在仅使用一个专门化参数设置示例时没有歧义 - 如预期的那样,const float(**)[3]被解析为Ty const**并且Ty = float const[3]

感谢Peter Alexander,我也用g ++试过我的简单例子(2个模板参数),它按预期工作,没有歧义。也许这可能是一个编译器问题?

让我提出一些解决方法:

  • 如果你真的要修改的MSVC标准库,你可以添加一个专业化_Ptr_cat_helper < const Ty (**)[3], const Ty (**)[3] >它完全适合和解决该不确定性。不幸的是,你必须明确提供维度(3)。
  • 请勿使用阵列此处。使用std::array(可在VS08 tr1)或结构或纯指针(float const*而不是float const[3]
  • 使用一个简单的包装:

    template < typename T > struct wrapper { T wrapped; } 
    std::vector < wrapper <TPoint> const* > m; 
    

    工作正常,我。

编辑:这里是我使用的示例:

#include <typeinfo> 
#include <iostream> 

template < typename T1, typename T2 > 
struct Spec 
{ 
    static const char* check() { return "plain"; } 
    typedef void Value; 
}; 

#define MAKE_SPEC(ARG0, ARG1) \ 
template < typename T > \ 
struct Spec < ARG0, ARG1 > \ 
{ \ 
    static const char* check() { return #ARG0 ", " #ARG1; } \ 
    typedef T Value; \ 
} 

MAKE_SPEC(T**, T**); 
MAKE_SPEC(T**, T const**); 
// can do more, but need not to.. 

int main() 
{ 
    typedef Spec < const float(**)[3], const float(**)[3] > MySpec; 

    std::cout << MySpec::check() << " -- " << typeid(MySpec :: Value).name(); 
} 
+0

'也许这可能是一个编译器问题' - 我期望它成为一个图书馆问题。仍然+1分析 – sehe

+0

由于我写的一个小例子使用g ++编译得很好,而不是MSVC,所以我认为这不是库问题。我已经遇到了一些(确认的)编译器错误,并且知道这些是非常罕见的 - 因此试图保守地制定它。 – dyp

+1

咦?库的实现是完全不同的......我并不是说它不能成为编译器问题,但直到你,例如,显示GCC + STLPort编译这个,而MSVC + STLPort没有基础,但没有基础 – sehe