manatttta
manatttta

Reputation: 3130

Function template return type deduction

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.

Upvotes: 11

Views: 14517

Answers (5)

W.F.
W.F.

Reputation: 13988

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

Upvotes: 12

Edgar Rokjān
Edgar Rokjān

Reputation: 17483

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.

Upvotes: 5

rubyyhj
rubyyhj

Reputation: 51

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

Upvotes: 3

Micha Wiedenmann
Micha Wiedenmann

Reputation: 20873

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

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

Upvotes: 21

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

Upvotes: 6

Related Questions