Reputation: 3130
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)
, NodeType
should 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
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
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
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
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
Reputation: 171177
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