2012-01-11 21 views
1

在下面的代碼中,當代碼被註釋掉時,代碼按預期工作 - Type與(第一個)模板參數匹配。以下模板代碼的奇怪行爲

但是,如果我取消註釋它,Type變爲char而不是std::string。這與MSVC和GCC相同。所以,當我爲StripTag專門化一個帶有一個和兩個參數的標籤模板,但是當我用三個參數完全相同的方式對它進行專門化時,我會得到這種奇怪的行爲。

任何人有任何想法?

代碼如下:

#include <typeinfo> 
#include <stdio.h> 
#include <string> 

template <typename T> 
struct StripTag 
{typedef T Type;}; 

template<typename T, template<typename T> class Tag > 
struct StripTag<Tag<T> > 
{ typedef typename StripTag<T>::Type Type; }; 

template<typename T, typename X, template<typename T, typename X> class Tag > 
struct StripTag<Tag<T,X> > 
{ typedef typename StripTag<T>::Type Type; }; 

/* 
//UNCOMMENT THIS AND RECOMPILE 
template<typename T, typename X, typename Y, template<typename T, typename X, typename Y> class Tag > 
struct StripTag<Tag<T,X,Y> > 
{ typedef typename StripTag<T>::Type Type; }; 
*/ 

template <class C> 
struct Test 
{ 
typedef C Type; 
}; 

template <typename A, typename B> 
struct Blah{}; 

int main() 
{ 

    printf("typeid of StripTag=\t%s\n", typeid(StripTag<std::string>::Type).name()); 
    printf("typeid of StripTag2=\t%s\n", typeid(StripTag<Blah<std::string, bool> >::Type).name()); 
    printf("typeid of Test=\t\t%s\n", typeid(Test<std::string>::Type).name()); 
    printf("typeid of std::string=\t%s\n", typeid(std::string).name()); 
} 
+0

刪除了[tag:c]標籤,因爲這是純粹的C++代碼。 – Xeo 2012-01-11 18:53:56

回答

3

這是因爲std::string實際上只是

std::basic_string<char, std::char_traits<char>, std::allocator<char>> 

這一個typedef,正如你所看到的,是一個有三個類型參數的類模板。

當你有一個StripTag專業化,它將三參數類模板作爲其參數之一時,該專業化比std::string更好地匹配主類模板(因爲它更具體)。

+0

哦:)是的,我完全忘了那個。這解釋了這一切。非常感謝 – 2012-01-11 19:02:40