2013-04-08 52 views
14

爲什麼std::remove_const不能將const T&轉換爲T&?這個不可否認的虛構的例子演示了我的問題:std :: remove_const與常量引用

#include <type_traits> 

int main() 
{ 
    int a = 42; 
    std::remove_const<const int&>::type b(a); 

    // This assertion fails 
    static_assert(
     !std::is_same<decltype(b), const int&>::value, 
     "Why did remove_const not remove const?" 
    ); 

    return 0; 
} 

上述案例是十分容易解決,所以對於背景下,想象一下以下內容:

#include <iostream> 

template <typename T> 
struct Selector 
{ 
    constexpr static const char* value = "default"; 
}; 

template <typename T> 
struct Selector<T&> 
{ 
    constexpr static const char* value = "reference"; 
}; 

template <typename T> 
struct Selector<const T&> 
{ 
    constexpr static const char* value = "constref"; 
}; 

int main() 
{ 
    std::cout 
     << Selector<typename std::remove_const<const int&>::type>::value 
     << std::endl; 

    return 0; 
} 

在上面的例子中,我期望reference被顯示,而不是constref

+0

請記住,沒有這樣的東西作爲const引用,只有const的引用。 – xaxxon 2016-07-14 09:19:17

回答

13

std::remove_const刪除頂級const -qualifications。在const T&(相當於T const&)中,限定條件不是頂層的:實際上,它不適用於引用本身(因爲引用根據定義是不可變的,所以引用本身沒有意義),而是適用於引用類型。

表52中的段C++ 11所標準規定的20.9.7.1,關於std::remove_const

的構件的typedef類型應命名相同類型T除了 任何頂層常量 - 限定符已被刪除。 [remove_const<const volatile int>::type計算結果爲 volatile int,而remove_const<const int*>::type評估 到const int*。 - 端示例]

爲了剝離const遠,首先必須施加std::remove_reference然後申請std::remove_const,然後(如果需要的話)應用std::add_lvalue_reference(或無論是在你的情況而定)。

注:作爲Xeo在註解中提到的,可以考慮using an alias template such as Unqualified執行前兩個步驟,即除掉那些參考,然後剝去該const - (和volatile-)資格。

+1

前兩個通常在「不合格」別名下組合在一起。 – Xeo 2013-04-08 19:40:38

+0

@Xeo:編輯,謝謝。 – 2013-04-08 19:44:43

+0

啊,我現在明白了。非常感謝解釋。 :) – dafrito 2013-04-08 20:24:20