尝试使用std :: add_const将T&转换为const T&

时间:2022-10-29 12:20:10

I have a T& which has a const and non-const version of a function. I want to call the const version of the function. I try using std::add_const to turn T& into const T& but it doesn't work. What am I doing wrong and how can I fix it?

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

Here is a simple example.

这是一个简单的例子。

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

Output: int&

6 个解决方案

#1


6  

Type traits are a very laborious way of approaching this. Simply use template type deduction:

类型特征是一种非常费力的方法来处理这个问题。只需使用模板类型扣除:

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

#2


4  

References cannot be cv-qualified, so std::add_const applied to a reference type leaves it unchanged. In this particular case you should just do

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

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

but in general you will have to transform the reference type T like this:

但一般来说,你必须像这样转换引用类型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;
};

#3


2  

std::add_const does nothing for a reference, since a reference can't be const qualified, only what it references can be.

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

In your case, a simple solution is to make a const version:

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

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

or if you don't want to specify an explicit type:

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

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

#4


2  

If you just want to prevent treating an expression as mutable, you could use std::cref:

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

#include <functional>

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

Here cref returns a std::reference_wrapper<const int> struct, which implicitly converts back to const int&.

这里cref返回一个std :: reference_wrapper 结构,它隐式转换回const int&。

If you want to actually do something with the corresponding reference-to-const-something type, either create your own trait as @Brian suggested, or use decltype on your own wrapper function as @BenVoigt suggested, or you could do something like this if you really still want to take advantage of cref:

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

int main()
{
    int a = 0;
    int& r = a;
    using ConstRefT = decltype(std::cref(r))::type &;
}

#5


1  

The general answer to how to do manual overload resolution is to cast the function pointer, i.e. here static_cast<(void(*)(const int&)>(f)(r). Uhm, I hope I got the parentheses right. In this specific case you can alternatively just cast the argument, f( static_cast<const int&>( r ) ), since static_cast can do any implicit conversion.

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

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

If you want to generalize that by composing the standard library's type modifiers, then you can do it like this:

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

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

Since that's pretty ugly I recommend just defining a general const-adder, or for an ad-hoc thing declaring a reference to const locally and use that as argument.

由于这非常难看,我建议只定义一个常规const-adder,或者用于在本地声明对const的引用并将其用作参数的ad-hoc事物。

A general const-adder can go like this:

一般的const-adder可以像这样:

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

#6


-1  

const_cast is what you need. See: http://www.cplusplus.com/doc/tutorial/typecasting/

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

#1


6  

Type traits are a very laborious way of approaching this. Simply use template type deduction:

类型特征是一种非常费力的方法来处理这个问题。只需使用模板类型扣除:

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

#2


4  

References cannot be cv-qualified, so std::add_const applied to a reference type leaves it unchanged. In this particular case you should just do

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

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

but in general you will have to transform the reference type T like this:

但一般来说,你必须像这样转换引用类型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;
};

#3


2  

std::add_const does nothing for a reference, since a reference can't be const qualified, only what it references can be.

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

In your case, a simple solution is to make a const version:

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

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

or if you don't want to specify an explicit type:

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

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

#4


2  

If you just want to prevent treating an expression as mutable, you could use std::cref:

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

#include <functional>

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

Here cref returns a std::reference_wrapper<const int> struct, which implicitly converts back to const int&.

这里cref返回一个std :: reference_wrapper 结构,它隐式转换回const int&。

If you want to actually do something with the corresponding reference-to-const-something type, either create your own trait as @Brian suggested, or use decltype on your own wrapper function as @BenVoigt suggested, or you could do something like this if you really still want to take advantage of cref:

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

int main()
{
    int a = 0;
    int& r = a;
    using ConstRefT = decltype(std::cref(r))::type &;
}

#5


1  

The general answer to how to do manual overload resolution is to cast the function pointer, i.e. here static_cast<(void(*)(const int&)>(f)(r). Uhm, I hope I got the parentheses right. In this specific case you can alternatively just cast the argument, f( static_cast<const int&>( r ) ), since static_cast can do any implicit conversion.

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

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

If you want to generalize that by composing the standard library's type modifiers, then you can do it like this:

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

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

Since that's pretty ugly I recommend just defining a general const-adder, or for an ad-hoc thing declaring a reference to const locally and use that as argument.

由于这非常难看,我建议只定义一个常规const-adder,或者用于在本地声明对const的引用并将其用作参数的ad-hoc事物。

A general const-adder can go like this:

一般的const-adder可以像这样:

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

#6


-1  

const_cast is what you need. See: http://www.cplusplus.com/doc/tutorial/typecasting/

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