2014-03-24 87 views
0

在C++ 03中,我使用gcc v3.4.6構建了以下代碼,但我不明白爲什麼調用_setValueSafeFails()時出現編譯器錯誤,因爲調用類似_incrValueSafe()的代碼不會。爲什麼volatile模板參數在一種情況下需要volatile,而不是其他情況?

Test.h:

class Test 
{ 
public: 
    void test(); 

    template<typename T> void _incrValueSafe(T &value) { 
    ++value; 
    } 

    template<typename T> void _setValueSafeFails(T &value, const T setVal) { 
    value = setVal; 
    } 

    template<typename T> void _setValueSafeWorks(volatile T &value, const T setVal) { 
    value = setVal; 
    } 

    volatile bool _testValue; 

}; 

Test.cpp的:

#include "Test.h" 

void Test::test() { 
    _incrValueSafe(_testValue); 
    _setValueSafeFails(_testValue, true); 
    _setValueSafeWorks(_testValue, true); 
} 

Test.cpp: In member function `void Test::test()': 
Test.cpp:5: error: no matching function for call to `Test::_setValueSafeFails(volatile bool&, bool)' 

不應該_incrValueSafe()得到同樣的錯誤,因爲在它的簽名沒有volatile要麼?這兩者如何對待不同,還是隻是一個編譯器錯誤?

+0

(已無關,與你的問題,但是,這些被保留的符號,你不應該_帶領你的變量名) – IdeaHat

+0

我以爲是被保留雙下劃線,但這些都是內上課,所以不應該是一個問題。 – WilliamKF

回答

1

正如其他人所解釋的那樣,第一個參數綁定到_testValue意味着 即Tvolatile bool,而第二個參數綁定到true 意味着T僅僅是bool(不volatile修飾符)。該 clang編譯器提供了一個很好的診斷:

clang++ -o main -std=c++1y -pedantic -Wall -stdlib=libc++ main.cpp -stdlib=libc++ 
main.cpp:26:5: error: no matching member function for call to '_setValueSafeFails' 
    _setValueSafeFails(_testValue, true); 
    ^~~~~~~~~~~~~~~~~~ 
main.cpp:12:35: note: candidate template ignored: deduced conflicting types for parameter 'T' ('volatile bool' vs. 'bool') 
     template<typename T> void _setValueSafeFails(T &value, const T setVal) { 
           ^
main.cpp:9:13: warning: incrementing expression of type bool is deprecated [-Wdeprecated-increment-bool] 
      ++value; 
      ^~~~~~ 
main.cpp:25:5: note: in instantiation of function template specialization 'Test::_incrValueSafe<volatile bool>' requested here 
    _incrValueSafe(_testValue); 
    ^
1 warning and 1 error generated. 
make: *** [main] Error 1 

關於領導強調:我只是避開他們,部分是爲了避免對 爭論什麼是或不是嚴格的法律。我更喜歡流行的約定:前綴 私有變量m_,並且不要以任何 特殊方式修飾私有函數名稱。 (前導下劃線是在Python, 但當然,私有成員德rigeur,C++是一個非常不同的語言),爲了記錄在案,聖 標準說以下內容:

17.6.4.3.2 Global names [global.names]


  1. 名稱和函數簽名的某些集始終是保留給 實現:

    - 每個名稱包含雙下劃線__或以 下劃線開頭,後面跟着大寫字母(2.12),保留給 實現用於任何用途。

    - 以下劃線開頭的每個名稱都保留爲 實現,以用作全局名稱空間中的名稱。

1

typename T_incrValueSafevolatile bool

1

由於

template<typename T> void _setValueSafeFails(T &value, const T setVal) { 
    value = setVal; 
} 

將被實例化到:

void _setValueSafeFails(volatile bool &value, const volatile bool setVal) 
0

類型揮發性布爾和布爾是不同的類型,並導致在_setValueSafeFails的不匹配。

你可以這樣做:

class Test 
{ 
public: 
    void test(); 
    template<typename T, typename U> void _setValueSafeA(T &value, const U setVal) { 
    value = setVal; 
    } 
    template<typename T> void _setValueSafeB(T &value, const T& setVal) { 
    value = setVal; 
    } 

    volatile bool _testValue; 

}; 

void Test::test() { 
    volatile bool true_value = true; 
    _setValueSafeA(_testValue, true); 
    _setValueSafeB(_testValue, true_value); 
} 
相關問題