简体   繁体   中英

C++11 trailing return member function using decltype and constness

I am trying to understand the trailing return based new function declaration syntax in C++11, using decltype.

In the following code, I am trying to define a member function returning a const & to allow for read-only access to i

#include <iostream>
#include <type_traits>

struct X {
    int &i;

    X(int &ii) : i(ii) {}

//    auto acc() const -> std::add_const<decltype((i))>::type { return i; } // fails the constness test
    auto acc() const -> decltype(i) { return i; } // fails the constness test
//    const int &acc() const { return i; } // works as expected   
};

void modify_const(const X &v) {
    v.acc() = 1;
}

int main() {
    int i = 0;
    X x(i);

    modify_const(x);
    std::cout << i << std::endl;

    return 0;
}

As mentioned in the comments, only the last commented version of acc() works, whereas using the others, the code just compiles and prints value 1 .

Question : How do we have to define the acc() function using the new function declaration syntax based on decltype , such that the compilation here fails due to returning a const &int in modify_const , or in other words, such that acc() has a proper const &int return type.

Remark : using int i; instead of int &i; as the member variable in X produces a compile error, as expected.

Edited to better distinguish between constness of v and X::i , respectively. It is the latter I am trying to impose in acc() .

The problem is that decltype((i)) return int& and apply const to that type has no effect. You want something like

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

... and then use

auto acc() const -> typename add_ref_const<decltype((i))>::type { return i; }

That is, the const needs to go between the type T and the & . The solution would have been obvious if you had put the const into the correct location: const should go to the right .

There's nothing illegal about a const member function modifying the target of a pointer to non-const, even if that pointer was gotten from a member variable.

From the compiler's perspective, int& IS the correct return type.

Your " modify_const " function is incorrectly named. i is what gets modified, and is not const .

Simply add an & to the left and skip the trailing return type.

struct X {
    int &i;

    X(int &ii) : i(ii) {}

    auto& acc() const { return i; } // Returns const reference
    auto& acc() { return i; } // Returns non-const reference
    const auto& acc() const { return i; } // Add const to the left to make it even more readable
};

Note that using this syntax you can declare the member variable after you have declared the function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM