2016-02-10 49 views
0

我在使用add_const typetrait應用於轉發引用類型的場景中。一切看起來像沒有常量被添加到類型,所以我做了一個小例子來驗證是這種情況(PrintType是一個不完整的類型,將導致編譯錯誤,迫使編譯器吐出錯誤中的模板參數的名稱消息):add_const將不適用於轉發引用

#include <iostream> 
#include <type_traits> 
#include <complex> 


template <class T> 
struct PrintType; 

template <class T> 
void f(T&& arg) 
{ 
    PrintType<std::add_const_t<decltype(arg)>> local; 
    (void)local; 
} 


int main() 
{ 
    std::complex<double> co; 
    f(co); 
} 

錯誤消息says

main.cpp: In instantiation of 'void f(T&&) [with T = std::complex<double>&]': 

main.cpp:20:9: required from here 

main.cpp:12:48: error: 'PrintType<std::complex<double>&> local' has incomplete type 

    PrintType<std::add_const_t<decltype(arg)>> local; 

即性狀轉化的我的類型的T = std::complex<double>&代替T = std::complex<double> const&

+0

爲了清楚起見,您希望根據參數的右值來查看'PrintType const&gt;或'PrintType const &&>'? – TBBle

回答

3

類型TR ait按預期工作。您應該考慮您正在嘗試做什麼,即將常量添加到參考中。 你不能重新綁定參考(它是不可變),所以基本上任何引用是const參考

T& == T& const 

我想什麼你希望做的是創造一個const類型的引用(這讓我想起這俊男來完成這種方式,同樣的原因const iterator VS const_iterator啄),你不能一個的typedef參考類型提到一個const類型這樣:

typedef T& ref_t; 
typedef const ref_t const_ref_t; // This is not T const& !! 

綜上所述,添加常量爲引用類型使得const引用(這是同樣作爲參考),而不是一個const類型

+0

這就是我正在嘗試做的,我編輯了這個問題來提及它。 –

1

對於像這種情況的參考,它可以是有用的一種類型的將參考轉換爲新類型的特徵。這可以補充constvolatile相同的另一個特徵,實現幾乎相同。在你的情況下,如果你使用T而不是decltype(arg)應該只需要擔心左值引用。但是,如果使用lambda表達式,那麼肯定也需要擔心右值引用。

下面是一個簡單的實現:

template<typename T, bool ApplyLvalueRef, bool ApplyRvalueRef> 
struct apply_ref { 
    static_assert(!(ApplyLvalueRef && ApplyRvalueRef), "Improper use: T cannot be & and &&"); 

    using possibly_lref = std::conditional_t< 
     ApplyLvalueRef, 
     std::add_lvalue_reference_t<T>, 
     T 
    >; 

    using type = std::conditional_t< 
     ApplyRvalueRef, 
     std::add_rvalue_reference_t<possibly_lref>, 
     possibly_lref 
    >; 
}; 

template<typename From, typename To> 
struct transfer_ref : apply_ref<To, std::is_lvalue_reference<From>{}, std::is_rvalue_reference<From>{}> {}; 

template<typename From, typename To> 
using transfer_ref_t = typename transfer_ref<From, To>::type; 

乍一看,似乎有點傻有左值與右值不同的布爾值。但是,這也不允許應用。永遠不應該存在這兩種情況都是正確的情況,這是由靜態斷言強制執行的。

現在,我們可以很容易地寫出函數:

template <class T> 
void f(T&& arg) 
{ 
    using with_const = std::add_const_t<std::remove_reference_t<T>>; 
    PrintType<transfer_ref_t<T, with_const>> local; 
    (void)local; 
} 

由於我們不能適用const到參考,我們必須剝離,添加const到稱爲類型,然後添加返回參考。

相關問題