2017-06-19 77 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