簡體   English   中英

add_const無法與轉發引用一起使用

[英]add_const won't work with forwarding references

我將add_const類型特征應用於轉發引用類型時使用它。 一切看起來都沒有添加PrintType ,因此我舉了一個小例子來驗證這種情況( PrintType是不完整的類型,它將導致編譯錯誤,從而迫使編譯器在錯誤中吐出模板參數的名稱信息) :

#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); 
}

該錯誤消息

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&

類型特征按預期工作。 您應該考慮要嘗試做的事情,這就是將常量添加到引用中。 您不能重新綁定引用 (它是不可變的),因此基本上任何引用都是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引用(與引用相同),而不是對const類型的引用

對於此類情況,具有將引用轉換為新類型的類型特征可能會很有用。 這可以補充對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添加到所引用的類型,然后再添加引用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM