2010-06-18 79 views
11

請,看看有什麼我試圖做的事:爲什麼不允許模板專門化在不同的命名空間中?

#include <iostream> 
namespace first 
{ 
template <class T> 
class myclass 
{ 
    T t; 
public: 
    void who_are_you() const 
    { std::cout << "first::myclass"; } 
}; 
} 
namespace second 
{ 
using first::myclass; 
template <> 
class myclass <int> 
{ 
    int i, j; 
public: 
    void who_are_you() const 
    { std::cout << "second::myclass"; } 
}; 
} 

這是不允許的。您能否請,澄清爲什麼不能專門化在不同的命名空間,什麼是可用的解決方案?另外,是否在C++ 0x中修正了一些問題?

這將讓我舉例來說,專門std::maxstd::swapstd::numeric_limits等。不加東西::std::訴諸未定義行爲?


@AndreyT下面是我,雖然我會使用它:

// my_integer is a class 
std::numeric_limits<my_integer>::max(); // specialized std::numeric_limits for my_integer 

可以這樣做?

+0

作爲替代方案,您是否可以創建一個從標準繼承的新模板? – Cogwheel 2010-06-18 18:47:22

+4

根據§17.4.3.1/ 1:「程序可以將任何 標準庫模板的模板特化添加到名稱空間標準。標準庫模板的這種專業化(完整或部分)會導致未定義的行爲,除非該聲明依賴於用戶 - 外部鏈接的定義名稱,除非專業化符合原始模板的標準庫要求。「所以,雖然有限制,你可以*在適當的情況下將這樣的特化添加到':: std ::'。 – 2010-06-18 18:52:52

+0

@jerry棺材我認爲添加任何東西都會導致未定義的行爲!請提供答案解釋如何滿足這些要求? – AraK 2010-06-18 19:00:12

回答

7

C++ 2003,§17.4.3.1/ 1:「程序可以將任何標準庫模板的模板特化添加到名稱空間標準中。標準庫模板的這種特殊化(完整或部分)會導致未定義的行爲,除非該聲明依賴於用戶定義的外部鏈接名稱,並且除非專業化符合原始模板的標準庫要求。「

這樣,你被允許專門庫模板,把你的專業化命名空間std,只要它依賴於用戶定義類型,滿足了原始模板的要求。

你在你編輯的問題中的代碼似乎是一個用戶定義的名稱(大概)有外部鏈接的專門化,所以你不應該有任何問題,這部分事情。

這隻留下您的專業化符合原始模板要求的要求。對於你的類型來說,大部分這可能只是微不足道的。我可以看到的唯一可能不明顯的部分是,您似乎必須爲整個模板提供專業化,而不僅僅是numeric_limits::max()。也就是說,你必須這樣做(例如應該在球場的128位無符號整數型):

namespace std { 
template <> 
class numeric_limits<my_integer> { 
public: 

    static const bool is_specialized = true; 
    static T min() throw() { return 0; 
    static T max() throw() { return /* 2^128-1 */; } // *** 
    static const int digits = 128; 
    static const int digits10 = 38; 
    static const bool is_signed = false; 
    static const bool is_integer = true; 
    static const bool is_exact = true; 
    static const int radix = 2; 
    static T epsilon() throw() { return 0; } 
    static T round_error() throw() { return 0; } 
    static const int min_exponent = 0; 
    static const int min_exponent10 = 0; 
    static const int max_exponent = 0; 
    static const int max_exponent10 = 0; 
    static const bool has_infinity = false; 
    static const bool has_quiet_NaN = false; 
    static const bool has_signaling_NaN = false; 
    static const float_denorm_style has_denorm = denorm_absent; 
    static const bool has_denorm_loss = false; 
    static T infinity() throw() { return 0; } 
    static T quiet_NaN() throw() { return 0; } 
    static T signaling_NaN() throw() { return 0; } 
    static T denorm_min() throw() { return 0; } 
    static const bool is_iec559 = false; 
    static const bool is_bounded = true; 
    static const bool is_modulo = true; 
    static const bool traps = false; 
    static const bool tinyness_before = false; 
    static const float_round_style round_style = round_toward_zero; 
}; 
} 

不少這些都是真的FP類型,並且不需要對整數類型有意義;我相信他們仍然需要實施。

+0

感謝您提供答案。請稍微澄清一下,外部聯繫是什麼意思。如果我的圖書館只是一個頭,行爲是不確定的? – AraK 2010-06-18 19:09:19

+2

否 - 「外部鏈接」大多意味着它不是「靜態的」或匿名的命名空間。 – 2010-06-18 19:23:46

+0

太好了。現在很清楚:) – AraK 2010-06-18 19:31:45

-4

爲什麼會出現這樣的問題?如果不理解甚至很難開始回答。

專業化修改主模板。它不以任何方式與主模板「分離」。在某種程度上,作爲一個高層次的概念,它仍然是相同的模板(儘管在較低層次上它被定義爲獨立模板)。所以,由於顯而易見的原因,它與主模板位於同一個命名空間中。

對不起,我無法提供更好的解釋,因爲我不明白這樣的問題會出現。

順便說一句,你是什麼意思的「在不同的命名空間」?你想要專業化成爲不同命名空間的成員?或者你想讓你的特化在源代碼的不同名字空間中定義,但仍然是原名稱空間的成員?

3

它複雜的事情:

namespace first 
{ 
    template <class T> class TArray; 
} 

namespace second 
{ 
    using first::TArray; 

    template <class U> class TArray < Node<U> >; 
    //       ^
    // Only there do you realize it's a specialization and not another template 
} 

我理解你的無奈,我常常想同樣的事情。這似乎是絕對可能的,我當然不會購買邏輯分組參數,但是我必須承認,編譯器編寫者需要付出更多努力,正確解析C++已經夠困難了。

模板是在C有點凌亂++如果你想要我的意見,但後來它很容易與經驗中獲益,並在看到20年使用:)後說

+0

@Matthiew M.謝謝。好答案。 – AraK 2010-06-18 18:59:08

相關問題