Question: Function template return type deduction

Question

Function template return type deduction

Answers 5
Added at 2017-01-02 13:01
Tags
Question

I have some class C with const and non-const getters for some generic type Node:

template <typename NodeType>
class CParent{};

class Node {};

class C : public CParent<Node> {
    Node&       getNode(Index i);
    const Node& getNode(Index i) const;
};

Now I want to create an alias function that call getNode for an object of class C:

template <class CType>
NodeType& AliasGetNode(CType* cobject);

But how do I deduce NodeType? i.e., if I call AliasGetNode<const C>(c) and AliasGetNode<C>(c), NodeTypeshould be respectively const Node&and Node&.

How can I do this?

I tried the result_of and decltype approaches but have not been successful.

Answers to

Function template return type deduction

nr: #1 dodano: 2017-01-02 13:01

Define a simple helper trait, which will add/remove const from a type based on whether another type is const:

template <class Src, class Dst>
using copy_const = typename std::conditional<
  std::is_const<Src>::value,
  const Dst,
  typename std::remove_const<Dst>::type
>::type;

And use it:

template <class CType>
copy_const<CType, NodeType>& AliasGetNode(CType* cobject);
nr: #2 dodano: 2017-01-02 13:01

Let the compiler deduce the return type (as of C++14):

template <class CType>
decltype(auto) AliasGetNode(CType& cobject)
{
    return cobject.getNode(0);
}
nr: #3 dodano: 2017-01-02 13:01

You should write two alias functions, one for non-const instance and the other for const instance:

template <class CType>
const NodeType& AliasGetNode(const CType* cobject) const;  // for const instance. 
// The function must be const since the only difference between return type will cause redefinition error.

template <class CType>
NodeType& AliasGetNode(CType* cobject);  // for non-const instance

The instances declared const will call the const functions if there are overload functions. Of course, non-const instances will call the non-const version of the overload function. For example:

class Aclass {
    public:
       string test() { return "calling non-const function"; }
       string test() const { return "calling const function"; }
};

int main() {
    Aclass a;
    const Aclass b;

    cout << a.test() << endl;
    cout << b.test() << endl;

    return 0;
}

The result will be:

calling non-const function
calling const function
nr: #4 dodano: 2017-01-02 13:01

Since C++14 the return type of a function may be deduced by the compiler:

template<typename CType>
decltype(auto) AliasGetNode(CType& cobject) {
    return cobject.getNode();
}

When you call AliasGetNode on the object of type Node, CType is deduced to Node. But if you call AliasGetNode on the object of type const Node, CType is deduced to const Node.

It is important to make return type of AliasGetNode as decltype(auto), otherwise you will miss a reference and constness for the returned type.

nr: #5 dodano: 2017-01-02 14:01

I would recommend the:

template <class CType>
auto AliasGetNode(CType& cobject) -> decltype(cobject.getNode(0))
{
    return cobject.getNode(0);
}

This should fairly work since c++11

Source Show
◀ Wstecz