Apologies for the cryptic title. Suppose this definition:
struct TestNode {
using CostType = double;
};
I would like to be able to define a class template like this:
template <typename NodeP,
typename MyPolicy = /* CostType of the node type corresponding to NodeP */ >
struct TT {
};
In the above definition, NodeP
can be either a simple or a smart pointer to a class that defines CostType
, such as TestNode
. The problem: how can one specify a default value for the MyPolicy
template parameter to be the CostType
of the node type corresponding to NodeP
?
Here is my solution so far:
// like std::remove_pointer, but works with smart pointers as well
template <typename PT> struct my_remove_pointer {
using type = typename
std::remove_reference< decltype( *((PT)nullptr) ) >::type;
};
struct TestNode {
using CostType = double;
};
template <typename NodeP,
typename MyPolicy = typename my_remove_pointer<NodeP>::type::CostType>
struct TT {
};
Is there a simpler approach to this problem? In particular, am I missing a standard library facility that could make the solution simpler?
Introduction of Smart PointersC++11 comes up with its own mechanism that's Smart Pointer. When the object is destroyed it frees the memory as well. So, we don't need to delete it as Smart Pointer does will handle it. A Smart Pointer is a wrapper class over a pointer with an operator like * and -> overloaded.
A smart pointer is like a regular (typed) pointer, like "char*", except when the pointer itself goes out of scope then what it points to is deleted as well. You can use it like you would a regular pointer, by using "->", but not if you need an actual pointer to the data. For that, you can use "&*ptr".
std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.
The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.
There is a helper class in the standard library called pointer_traits
. It looks like it's exactly what you want.
run online
#include <iostream>
#include <memory>
#include <typeinfo>
struct TestNode {
using CostType = double;
};
template <typename NodeP,
typename MyPolicy = typename std::pointer_traits<NodeP>::element_type::CostType>
struct TT {
typedef MyPolicy xxx;
};
int main () {
TT<TestNode*>::xxx a = 2.8;
TT<std::unique_ptr<TestNode>>::xxx b = 3.14;
std::cout << a << std::endl;
std::cout << b << std::endl;
return 0;
}
With some usings I may be a little more readable
template<typename T>
using remove_pointer_t = typename my_remove_pointer<T>::type;
template<typename T>
using cost_type_t = typename remove_pointer_t<T>::CostType;
Now in your code
template <typename NodeP,
typename MyPolicy = cost_type_t<NodeP>>
struct TT {
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With