2017-06-19 72 views
2

想象一下函數(RetrieveResult),通過指針/引用/值返回對象 - 我不知道也不想知道,因爲事情可能會改變。我只是想使用auto來存儲結果,並保護該對象免受當前範圍內的意外更改,或者例如,如果對象向上傳播。const auto和對象常量

這是很直觀的只是寫:

const auto result = RetrieveResult(); 

,一切工作正常,如果RetrieveResult通過值或引用返回一個對象。但是,如果函數返回一個指針,那麼常量將應用於該指針,而不是指向該指針所指向的對象。我仍然可以改變對象的方式。寫

const auto const result = .... 

導致編譯錯誤:

duplicate 'const'

當然,我可以聲明變量是這樣的: 常量自動* ... 常量自動* const的...

但這種方式使我接近指針,即它不是一個通用的解決方案。

是否有可能保持真正的恆定性,並在同一時間提供靈活性(具體類型的獨立性)?

+0

「我不想也不想知道」如果你不知道它是什麼,你該如何訪問這個對象?對於你所知道的,它可能是一個重載了' - >'的類,你認爲它是一個指針:P – Rakete1111

+0

@ Rakete1111,例如,我可能只是轉發對象,而不接觸它 – Alexey

+2

@Alexey如果你轉發它爲什麼你關心它指向的指針是否是'const'? – Rakete1111

回答

3

在圖書館基礎知識v2中,此實用程序std::propagate_const有實驗支持。你可以寫上的是,這是否對你頂部的類型特徵(如果你沒有std::propagate_const你可以考慮自己寫吧:))

namespace { 
    template <typename T, typename = std::enable_if_t<true>> 
    PropagateConst { 
     using type = T; 
    }; 
    template <typename T> 
    PropagateConst<T, std::enable_if_t<std::is_same< 
      decltype(*std::declval<std::decay_t<T>>()), 
      decltype(*std::declval<std::decay_t<T>>())>::value>> { 
     using type = std::propagate_const_t<std::decay_t<T>>; 
    }; 

    template <typename T> 
    using PropagateConst_t = typename PropagateConst<T>::type; 

    template <typename Type> 
    decltype(auto) propagate_const(Type&& in) { 
     return PropagateConst_t<std::add_rvalue_reference_t<Type>>{in}; 
    } 
} // <anonymous> 

// then use it like this 
const auto result = propagate_const(RetrieveResult()); 

注意,解決我上面只檢查在可能的指針類型中存在operator*。您可能需要考慮爲此編寫更廣泛的測試。

另請注意,此示例使用propagate_const示例中的參考摺疊,因此在您可能期望發生elision的情況下,至少需要採取某種舉措。您可以根據您的使用情況對其進行優化。我只是想我會概述我腦海中的一切。也許這將有助於

1
template<class T> 
struct very_const_t { using type=T; }; 
template<class T> 
struct very_const_t<T*> { using type=typename very_const_t<T>::type const*; }; 
template<class T> 
struct very_const_t<T&> { using type=typename very_const_t<T>::type const&; }; 

template<class T> 
typename very_const_t<T>::type&& 
very_const(T&& t) { return std::forward<T>(t); } 

則:

const auto result = very_const(RetrieveResult()); 

注意,這可以阻止省音。但是,我小心不要阻止移動語義。

這不會將const移動到智能指針中。如果您希望:

template<class T, class D> 
struct very_const_t<std::unique_ptr<T,D>> { using type=std::unique_ptr<typename very_const_t<T>::type const, D>; }; 

template<class T> 
struct very_const_t<std::shared_ptr<T>> { using type=std::shared_ptr<typename very_const_t<T>::type const>; }; 

會做它uniqueshared