Search code examples
c++c++11generic-programmingconst-reference

Allowing both pre-computed and computed-on-the-fly results


Consider:

template <typename T>
struct C {
    std::vector<int> f(const T &t) const {
        return t.f();
    }
};

T::f must compute the required vector. However, some T's pre-compute the vector and we would like to avoid creating a copy in such a case. Here is my attempt:

struct A {
    std::vector<int> f() const {
        std::vector<int> res{10, 20, 30}; // computing the vector.
        return res;
    }
};

struct B {
    const std::vector<int> &f() const {
        return v_; // returning reference to pre-computed vector.
    }
private:
    std::vector<int> v_{1, 2, 3};
};

template <typename T>
struct C {
    const std::vector<int> &f(const T &t) const {
        return t.f();
    }
};

int main() {
    using T = B; // For A, we get an error about returning reference to a local.
    C<T> c;
    T t;
    c.f(t);
    return 0;
}

As the comment in main indicates, for T=A, the above code is in error as it is returning a reference to the local variable. How can I accommodate for both T=A and T=B, such that the pre-computed vector B::v_ does not get copied?


Solution

  • Make C::f return the exact same type as T::f, by using decltype:

    template <typename T>
    struct C {
        auto f(const T &t) const -> decltype(t.f()) {
            return t.f();
        }
    };
    

    This will return by value when T = A, and by const& when T = B.

    wandbox example