试图使用std :: add_const来转变T&进入const T&

时间:2014-05-16 22:01:28

标签: c++

我有一个T&它有一个const和非const版本的函数。我想调用函数的const版本。我尝试使用std :: add_const来转换T&进入const T&但它不起作用。我做错了什么,我该如何解决?

这是一个简单的例子。

void f(int&)
{
    std::cout << "int&" << std::endl;
}

void f(const int&)
{
    std::cout << "const int&" << std::endl;
}

int main()
{
    int a = 0;
    int& r = a;
    f(static_cast<std::add_const<decltype (r)>::type>(r));
}

输出:int&

6 个答案:

答案 0 :(得分:6)

类型特征是一种非常费力的方法来解决这个问题。只需使用模板类型推导:

void f(int&)
{
    std::cout << "int&" << std::endl;
}

void f(const int&)
{
    std::cout << "const int&" << std::endl;
}

template<typename T>
const T& make_const(T& t) { return t; }

int main()
{
    int a = 0;
    int& r = a;
    f(make_const(r));
}

答案 1 :(得分:4)

引用不能是cv限定的,因此应用于引用类型的std::add_const会使其保持不变。在这种特殊情况下你应该做

f(static_cast<const int&>(r));

但一般情况下,你必须像这样转换引用类型T

template<typename T>
struct add_const_to_reference {
    typedef T type;
};

template<typename T>
struct add_const_to_reference<T&> {
    typedef const T& type;
};

template<typename T>
struct add_const_to_reference<T&&> {
    typedef const T&& type;
};

答案 2 :(得分:2)

std::add_const对参考没有任何作用,因为引用不能是const限定的,只能引用它。

在您的情况下,一个简单的解决方案是制作const版本:

int main()
{
    int a = 0;
    int& r = a;
    const int &const_r = r;
    f(const_r);
}

或者如果您不想指定显式类型:

int main()
{
    int a = 0;
    int& r = a;
    const auto &const_r = r;
    f(const_r);
}

答案 3 :(得分:2)

如果您只是想防止将表达式视为可变,可以使用std::cref

#include <functional>

int main()
{
    int a = 0;
    int& r = a;
    f(std::cref(r));
}

此处cref返回std::reference_wrapper<const int>结构,隐式转换回const int&

如果你想用相应的reference-to-const-something类型做一些事情,可以按照@Brian的建议创建你自己的特性,或者在@BenVoigt建议的你自己的包装函数上使用decltype,或者如果你真的想要利用cref

,你可以做这样的事情
int main()
{
    int a = 0;
    int& r = a;
    using ConstRefT = decltype(std::cref(r))::type &;
}

答案 4 :(得分:1)

如何进行手动重载解析的常规答案是强制转换函数指针,即static_cast<(void(*)(const int&)>(f)(r)。嗯,我希望我的括号正确。在这种特定情况下,您可以选择仅转换参数f( static_cast<const int&>( r ) ),因为static_cast可以执行任何隐式转换。

int main()
{
    int a = 0;
    int& r = a;
    f(static_cast<int const&>(r));
}

如果你想通过编写标准库的类型修饰符来概括它,那么你可以这样做:

f(static_cast<std::remove_reference<decltype(r)>::type const&>(r));

由于这非常难看,我建议只定义一般const - 加法器,或者在本地声明对const的引用并将其用作参数的临时事物。

一般const - 加法器可以这样:

template< class Type >
auto const_ref( Type const& r ) -> Type const& { return r; }

答案 5 :(得分:-1)

const_cast就是您所需要的。 请参阅:http://www.cplusplus.com/doc/tutorial/typecasting/