Changing deleter for std::unique_ptr - c++

I want to change default_deleter for std::unique_ptr. This is quite easy to achieve, but there is one inconvenient - I have to declare variables using 2 template parameters instead of one, something like this:
std::unique_ptr<MyType, MyDeleter<MyType>> myVar;
As you may see the declaration is long and I have a feeling I can use a shorter version, but I don't know how:)
Is it possible to declare some kind of MyUniquePtr<T> that will be the same as std::unique_ptr<T, MyDeleter<T>>?
EDIT: Matthieu M. already answered, but unfortunately I can't use this feature in Visual Studio as it's not implemented. Is there other way to have this behavior?

Actually it is, using template aliases:
template <typename T>
using MyUniquePtr = std::unique_ptr<T, MyDeleter<T>>;

If your compiler doesn't do template aliases yet, here's the C++03 idiom:
template <typename T>
struct MyUniquePtr {
typedef std::unique_ptr<T, MyDeleter<T> > type;
};
MyUniquePtr<MyType>::type var;
The setup is uglier, but the resulting usage is almost as short: you just need to add ::type.

Does your deleter need to be templated on the type of the object being deleted, or is it sufficient for the function call operator to be templated on the type of object being deleted?
Instead of:
template<typename T>
struct MyDeleter
{
void operator()(T* p) const { /* ... */ }
};
Can you write:
struct MyDeleter
{
template<typename T>
void operator()(T* p) const { /* ... */ }
};
This, of course, depends on what state MyDeleter has to maintain.

Another way conforming to c++03 is a subclass, which unfortunately requires you to reproduce the constructors. (This can be done easier, if your compiler supports variadic template arguments, which may be the case for current MSVC.)
template <class T>
class MyUniquePtr : public std::unique_ptr< T, MyDeleter<T> > {
public:
MyUniquePtr(args...) : std::unique_ptr< T, MyDeleter<T> >(args...) { }
};

You might want to consider writing your own version of a make_unique style function instead specialized for your custom allocation / deletion strategy. This also has the advantage that you can perform any specialized resource acquisition / allocation in an exception safe way. You can then declare your unique_ptr as auto and let type deduction work for you.

Related

How to request vector<T> as a template type argument

In general, how would you request vector<T> as a type in a template?
template<?vector<T>?>
void allocate() {
vector<T> vector;
}
To be more specific (the example above is a bit dumb), I'm using a service_locator<T> from this library and all of its members are static. The constructor and the destructor of that struct are deleted, therefore there is no such thing as an instance of a service_locator<T>. I'd like to write a function that does something, given some service_locator<T>. Something like the following.
template<?service_locator<T>?> // What do I write here?
T& assertedRef() {
assert(!service_locator<T>::empty(), "Value not initialized for that type!");
return service_locator<T>::ref();
}
My current workaround is to ask for T instead of service_locator<T>. This is a hassle for the callers because it's on them to figure out the underlying type the service_locator is operating on (most of them are aliased to something more readable).
You can use partial specialization for this. Since that's not supported for functions, you have to forward the call to a partially specialized class instance.
template <typename T>
struct AssertedRefFunctor {
static_assert(sizeof(T) == -1, "Not a service locator");
};
template <typename T>
struct AssertedRefFunctor<entt::service_locator<T>> {
T& operator()() {
if (entt::service_locator<T>::empty()) {
throw std::runtime_error("Value not initialized for that type!");
}
return entt::service_locator<T>::ref();
}
};
template <typename T>
auto assertedRef() -> decltype(std::declval<AssertedRefFunctor<T>>()()) {
return AssertedRefFunctor<T>{}();
}
Usage:
assertedRef<entt::service_locator<int>>();
Demo: https://godbolt.org/z/f-oUpY
C++ (at least C++17) does not support template parameter constraints like C# does (they were proposed for C++0x as "concepts" but withdrawn). But you can have a static assert using std::is_base_of.
And as a hint to whoever consumes your library, I'd name the template parameter as TVector and TVectorItem to be clear that it expects a vector<TVectorItem> derivative.
(And I agree with the (now deleted) comment that the Service Locator pattern is an anti-pattern. There are almost always better alternatives to using the Service Locator pattern - but we'd need to know more about your application before suggesting anything).
(And if you're using Visual Studio or MSBuild and want to build a statically-evaluated or constexpr DI container builder, consider using T4 for codegen instead of C++ templates).
#include <type_traits>
template<typename TVector, typename TVectorItem>
void allocate() {
static_assert( std::is_base_of<vector<TVectorItem>, TVector>::value, "TVector must derive from vector<TVectorItem>." );
TVector vector;
}
There are no direct way to do that.
In your case, you might do:
template <typename ServiceLocatorT>
auto assertedRef() -> decltype(ServiceLocatorT::ref())
{
assert(!ServiceLocatorT::empty(), "Value not initialized for that type!");
return ServiceLocatorT::ref();
}
In generic case, template classes might have aliases of there template (as done with STL std::vector<T>::value_type) that you can use.
At worst, you might create type_traits:
template <typename T> struct value_type;
template <typename T> struct value_type<std::vector<T>>
{
using type = T;
};
// ...

How can I get the C++ compiler to deduce T indirectly?

My template-fu is rather weak. I have this code:
template<typename T>
void Foo(void(*func)(T*)) { }
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
...but I'd like something more readable than C's nasty function pointer syntax of void(*func)(T*).
Someone on my team suggested this:
template<typename T>
struct Types
{
typedef void Func(T*);
};
template<typename T>
void Foo2(typename Types<T>::Func* func) {}
void Test2()
{
Foo2(Callback); // could not deduce template argument for 'T'
Foo2<int>(Callback); // ok
}
(I'm still debating whether this is actually more readable, but that's a separate issue.)
How can I help the compiler figure out what T is without needing to explicitly specify it in the caller?
You can extract T from the function type using a traits class.
template<class F>
struct CallbackTraits;
template<class T>
struct CallbackTraits<void(*)(T)>
{
typedef T ArgumentType;
};
Your example can be modified like this:
template<typename F>
void Foo(F func)
{
typedef typename CallbackTraits<F>::ArgumentType T;
}
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
This technique is used in the boost type-traits library:
http://www.boost.org/doc/libs/1_57_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html
This blog post goes into a bit more detail about the implementation of the technique:
https://functionalcpp.wordpress.com/2013/08/05/function-traits/
Unfortunately this approach hides the information in the signature of Foo about the constraints on the argument passed in. In the above example the argument must be a function of type void(T*).
This alternative syntax does the same as the original example while being slightly more readable:
template<typename T>
void Foo(void func(T*)) { }
Another alternative syntax that may be more readable can be achieved using c++11's alias templates as follows:
template<typename T>
using Identity = T;
template<typename T>
void Foo(Identity<void(T*)> func) { }
Unforunately the latest MSVC fails to compile this, reporting an internal compiler error.
You won't be able to deduce the type based on a nested name: there is no reason why different instantiations of the outer type won't define an identical inner type. You could use a using alias, though:
template <typename T>
using Function = auto (*)(T*) -> void;
template <typename T>
void Foo(Function<T>) {
}
Personally, I would recommend against using any of that, however: in practice it seems much more advisable to actually take a function object which later allows using object with suitable function call operators to be used. For callbacks it is quite common that you'll need to pass in some auxiliary data. That is, you would either use an unconstrained template or one which takes a type-erased type, depending on what you want to do exactly:
template <typename Fun>
void Unconstrained(Fun fun) {
}
template <typename T>
void TypeErased(std::function<void(T*)> fun) {
}
The unconstrained version has the advantage that it can potentially inline the function call but it has the disadvantage that every function object type creates a new instantiation and that the argument types are likely to vary. The type-erased version effectively has to do something like a virtual function call but there is just one instantiation of the function template (per argument type T, of course).
Admittedly, the type-erased version's type won't be deduced from a function pointer (or any other argument which isn't a std::function<void(X*)>), i.e., you may want to have a forwarding function
template <typename T>
void TypeErased(Function<T> fun) {
TypeErased(std::function<void(T)>(fun));
}
In C++98 and C++03 template argument deduction only works with functions (and methods).
I don't think the picture changed in the more recent standards.

Raise an exception for non-pointer template class?

I've got this queue class, actually, several that suffer from the same issue - performance will be poor if compiled with a type that has a lengthy copy ctor - the queue is locked during push/pop and the longer it is locked, the greater the chance of contention. It would be useful if the class would not compile if some developer tried to compile it with a 10MB buffer class, (instead of a pointer to it).
It seems that there is no easy way to restrict template parameters to base classes or any other type.
Is there some bodge I can use so that my class will not compile if the parameter is not a pointer to a class instance?
You can do this in several ways. As another answer points out you can do it with a static_assert (preferably from C++11/Boost although you can roll your own), although I'd recommend checking if it is actually a pointer and not just relying on the size. You can either roll your own or use an existing trait (available in C++11 too) depending on what system you're using:
template <typename T>
struct is_pointer {
enum { value = 0 };
};
template <typename T>
struct is_pointer<T*> {
enum { value = 1 };
};
template <typename T>
struct container {
static_assert(is_pointer<T>::value, "T must be a pointer");
void push(const T&);
T pop();
};
struct foo {};
int main() {
container<foo*> good;
container<foo> fail;
}
But that raises a bigger point. If your requirement is that you only ever point to things, why not interpret the template parameter like that to begin with? E.g. make your container:
template <typename T>
struct container {
void push(const T*);
T *pop();
};
instead of allowing people to specify non-pointer types in the first place?
Finally if you don't want to go down the static_assert road you can just specialise the container for pointer types only and not implement it for non-pointers, e.g.:
template <typename T>
struct container;
template <typename T>
struct container<T*> {
void push(const T*);
T *pop();
};
struct foo {};
int main() {
container<foo*> good;
container<foo> fail;
}
This still requires explicitly making the type a pointer, still causes compile time failure for non-pointer types, but doesn't need a static_assert or way of determining if a type is a pointer.
"Is there some bodge I can use so that my class will not compile if the parameter is not a pointer to a class instance?"
Not a bodge, but:
template<class T>
class MyContainer
{
public:
void AllMemberFunctions( T* in ){}
void OnlyAcceptTStars( T* in ){}
};
The user defines the type being held, and your functions only accept or handle pointers to that type.
(Or do what STL does, assume some intelligence on the part of the user and forget about the issue.)
Use a variant of static assert (just google for many possible implementations). Something like BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(void*)) should do the trick.
Yes, you can do it using static_assert. For example,
template<int N>
class Queue
{
static_assert(N < size, "N < size violated");
...
};

C++ template programming - Deferred function calls

I am looking for an elegant solution to the following problem. I have a task struct that I use for deferred function calls.
template <typename T> struct Task1
{
T Arg1;
Delegate<T> TaskDelegate;
};
The problem I'm having is this:
Task1<const Foo&> MyTask;
This will result in the parameter being held as a const reference. Does anyone know a nice solution to get round this? I could enforce rules such as the delegate signature always taking const& params but this seems restrictive. I could always have two task structs (one for ref and one for value) but this seems nasty.
The other solution would be to create the following:
template <typename T1, typename T2> struct Task1
{
T2 Arg1;
Delegate<T1> TaskDelegate;
};
Is there anyway to default T2 to be the same type as T1? That way whenever I have a method value signature I don't need to have the additional template params.
EDIT:
The template is used for a multithreaded task scheduler. Here is an example:
void MyClass::Populate(const std::string& instrText);
CTaskScheduler::Schedule(Task1<const std::string&>(this, &MyClass::Popluate, "MyString"));
You could take a look at the implementation of function<> either in boost or the upcoming standard. As a matter of fact, you can just use function<>. I think that the solution there was (before C++0x) to always store a copy of the arguments, if the user wants reference semantics they can use a reference wrapper.
As to how to get to a value, you can take a look at some simple metafunction to remove const or &:
// Remove reference:
template <typename T>
struct remove_reference {
typedef T type;
};
template <typename T>
struct remove_reference<T&> {
typedef T type;
};
Similarly for const.
You can use the boost.type_traits library to remove the const-ness of the parameter using boost::remove_const.
In addition to boost::type_traits, there is a boos::call_traits library specifically built to handle problems like this. It also provides mechanisms to avoid the references of references problem.
boost::remove_const should help you in this case:
template <typename T> struct Task1
{
typename boost::remove_const<T>::type Arg1;
Delegate<T> TaskDelegate;
};
Alternatively, you can avoid using boost if you use template specialization for const types:
template <typename T> struct Task1
{
T Arg1;
Delegate<T> TaskDelegate;
};
template <typename T> struct Task1<const T>
{
T Arg1;
Delegate<const T> TaskDelegate;
};
(Warning: untested)

Automatic Evaluation Strategy Selection in C++

Consider the following function template:
template<typename T> void Foo(T)
{
// ...
}
Pass-by-value semantics make sense if T happens to be an integral type, or at least a type that's cheap to copy.
Using pass-by-[const]-reference semantics, on the other hand, makes more sense if T happens to be an expensive type to copy.
Let's assume for a second that you are writing a library. Ideally, as a library implementer, your job is to provide your consumers with a clean API that is both as generic and efficient as possible. How then, do you provide a generic interface that caters to both types of argument passing strategies?
Here is my first attempt at getting this to work:
#include <boost/type_traits.hpp>
template<typename T> struct DefaultCondition
{
enum {value = boost::is_integral<T>::value /* && <other trait(s)> */};
};
template< typename T, class Condition = DefaultCondition<T> > class Select
{
template<bool PassByValue = Condition::value, class Dummy = void> struct Resolve
{
typedef T type;
};
template<class Dummy> struct Resolve<false, Dummy>
{
typedef const T& type;
};
public: typedef typename Resolve<>::type type;
};
Typical usage:
template<typename T> class EnterpriseyObject
{
typedef typename Select<T>::type type;
public: explicit EnterpriseyObject(type)
{
// ...
}
};
struct CustomType {};
void Usage()
{
EnterpriseyObject<int>(0); // Pass-by-value.
(EnterpriseyObject<CustomType>(CustomType())); // Pass-by-const-reference.
}
This, of course, indirectly breaks implicit template argument deduction for non-class templates:
template<typename T> void Foo(typename Select<T>::type)
{
// ...
}
void Usage()
{
Foo(0); // Incomplete.
Foo<int>(0); // Fine.
}
This can be "fixed" with the Boost.Typeof library and a macro, a la the WinAPI:
#define Foo(Arg) ::Foo<BOOST_TYPEOF((Arg))>((Arg))
Though this is just a quasi-portable hack.
As you can see, my general approach is not really satisfactory for all cases.
As a hobbyist programmer, I neither have real-world experience nor do I have access to production-quality code for reference. I also realize that this might seem like a bad case of premature optimization, but I'm genuinely interested in a couple of things:
Do you, or have you used this type of optimization* in the past?
Does the Boost (or any other public) library already provide similar functionality?
If the answer to #1 or #2 is a 'yes' -- how is the non-class template case handled?
Are there any obvious pitfalls that I'm not seeing with something like this?
Finally, is this even a sane thing to do?
* Not profiled. ;)
Yes. All the time. I use it myself.
Yes, use Boost.Utility's Call Traits :)
Usage would be...
template <typename T>
void foo(boost::call_traits<T>::param_type param)
{
// Use param
}
As far as I know, non-class templates are passed-by-value unless it is faster to not. Thanks to partial template specialization, it can be customized relatively easily.
Sorry, didn't really read what you did, it just looked like exactly what I went through a few months ago. Therefore, can't really answer this one. My recommendation is just to read through Boost.Utility.
Of course!