删除decltype中的引用(返回T而不是T&amp ;,其中T&是decltype) [英] Remove reference in decltype (return T instead of T& where T& is the decltype)

查看:251
本文介绍了删除decltype中的引用(返回T而不是T&amp ;,其中T&是decltype)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(如果您是C ++ 11专业人士,请跳至粗体字段.)

(If you're a C++11 pro, skip to the bold paragraph.)

假设我想编写一个模板方法,该方法调用并返回类型为模板参数的对象的结果:

Let's say I want to write a template method which calls and returns the result of a passed object which type is the template parameter:

template<ReturnType, T>
ReturnType doSomething(const T & foo) {
    return foo.bar(); // EDIT: Might also be an expression introducing a temp val
}

因此T必须具有方法ReturnType T::bar() const才能在这样的调用中使用:

So T has to have a method ReturnType T::bar() const in order to be used in a call like this:

struct MyClass {
    ...
    int bar() const;
    ...
};
...
MyClass object;
int x = doSomething<int, MyClass>(object);

由于类型推断,我们不必编写MyClass,该调用变为:

We don't have to write MyClass thanks to type deduction and the call becomes:

int x = doSomething<int>(object);

但是省略<int>也会导致编译错误,因为该方法不需要返回int即可随后分配给x(例如,它可以返回char).

But omitting <int> too results in a compilation error because the method doesn't require to return int in order to be assigned to x afterwards (it could return char for example).

在C ++ 0x/11中,我们具有autodecltype,我们可以用它们来推断模板方法的返回类型:

In C++0x/11 we have the auto and decltype with which we can use to deduce the return type of a template method:

template<T>
auto doSomething(const T & foo) -> decltype(foo.bar()) {
    return foo.bar(); // EDIT: Might also be an expression introducing a temp val
}

现在,编译器将找出foo.bar()的类型,并将其用作返回类型.对于我们的具体类MyClass,这将是一个int,并且满足以下条件:

The compiler will now find out what the type of foo.bar() is and just uses this as the return type. With our concrete class MyClass this will be an int and the following would suffice:

int x = doSomething(object);

现在我的问题是:

如果MyClass将bar()定义为返回int&,则doSomething(object)的返回类型也将是int& = decltype(foo.bar()).这是一个问题,因为G ++现在要求我返回对临时对象的引用.

If MyClass defines bar() as returning an int&, the return type of doSomething(object) will also be an int& = decltype(foo.bar()). This is a problem, since as G++ now complies that I'm returning reference to temporary.

我该如何解决?是否有类似remove_reference的东西可以像remove_reference(decltype(foo.bar()))那样使用?

How can I fix this? Is there something like remove_reference which can be used like remove_reference(decltype(foo.bar()))?

我考虑过只声明一个使用T&并返回T的辅助方法,然后将doSomething的返回类型定义为decltype(helper(foo.bar())).但是我必须要有更好的方法.

I thought about just declaring a helper method which takes a T& and returns a T and then define the return type of doSomething to be decltype(helper(foo.bar())). But there has to be a better way, I'm feeling it.

推荐答案

要删除引用,请执行以下操作:

To remove a reference:

#include <type_traits>

static_assert(std::is_same<int, std::remove_reference<int&>::type>::value, "wat");

在您的情况下:

template <typename T>
auto doSomething(const T& foo)
    -> typename std::remove_reference<decltype(foo.bar())>::type
{
    return foo.bar();
}


请清楚一点,请注意,按照书面形式返回引用就可以了:


Just to be clear, note that as written returning a reference is just fine:

#include <type_traits>

struct f
{
    int& bar() const
    {
        static int i = 0;
        return i;
    } 
};

template <typename T>
auto doSomething(const T& foo)
    -> decltype(foo.bar())
{ 
    return foo.bar();
}

int main()
{
    f x;
    return doSomething(x);
}

返回的引用可以简单地传递而不会出错.您在注释中的示例变得非常重要和有用:

The returned reference can simply be passed on without error. Your example in the comment is where it becomes important and useful:

template <typename T>
auto doSomething(const T& foo)
    -> decltype(foo.bar())
{ 
    return foo.bar() + 1; // oops
}

这篇关于删除decltype中的引用(返回T而不是T&amp ;,其中T&amp;是decltype)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆