Automatic Evaluation Strategy Selection in C++ - 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!

Related

Preventing accidental hiding (of a method provided by CRTP mixin)

I have a bunch of useful functions on the object of type T. Here T needs to provide some interface for the functions to work with it. There are several common implementations of the interface. So I made them working as mixins using CRTP.
template<class T>
struct InterfaceImpl {
using ImplType = InterfaceImpl<T>;
int foo();
...
};
struct MyData : public InterfaceImpl<MyData> {
...
};
template<class T>
void aUsefulFunction(T& t) {
//Working with `t`.
//This cast is to workaround an accidental hiding of `foo` by MyData.
static_cast<T::ImplType&>(t).foo();
}
I want the implementation InterfaceImpl (and other implementations also) are provided as it is in some reason. Hiding some of their methods could be very dangerous. Are their any way to enforce no overriding by child classes? I read link on a similar question, but the discussion does not give a satisfactory solution. If there is no reasonable way, I expect that the casting in the above code could give some safety. Or are there any other solution to solve the problem?
You can create a traits to see if T has foo and using static_assert on that:
typename <typename T, typename ...Ts>
using foo_type = decltype(std::declval<T>().foo(std::declval<Ts>()...));
template <typename T>
using has_foo = is_detected<foo_type, T>;
template<class T>
struct InterfaceImpl {
static_assert(!has_foo<T>::value, "T should not have foo method");
using ImplType = InterfaceImpl<T>;
int foo();
};
MyData can still hide foo with MyData::foo(int) or similar, but you will have compilation error instead if calling the wrong method.

How to prevent specialization of a C++ template?

The compiler doesn't complain when I do this ;-)
// Myfile.h
#include <iostream>
#include <vector>
namespace std
{
template<> class vector<int>
{
public:
vector ()
{
std::cout << "Happy Halloween !!!\n";
}
};
}
Is there any way to prevent this kind of undesirable specialization of a class/function template?
--EDIT--
I just used std:: as an example. What I'm looking for is a way to prevent this from happening to any template class.
What you do is specialize a standard library type inside a standard namespace.
Except for a few documented customization points (std::swap, std::hash<>) or specificly constrained specializations for User Defined Types (e.g. MySmartPtr<T>) this is against the specification and the result is undefined behaviour.
Edit: There is no mandatory diagnostic for this kind of rule violation.
To make it marginally harder for clients of your library to mess things up, you can do this trick:
namespace Public {
namespace Hidden { // DON'T TOUCH THESE!
template <typename> struct MyType { };
}
using Hidden::MyType;
}
Now, attempting to specialize MyType<> in namespace Hidden will fail.
No, the C++ language does not provide a general mechanism by which you can say "don't allow specializations of this template".
But it may not matter. For any instantiation that your code uses already, a user provided specialization will violate the one definition rule and their program may blow up in a fireball.
If you aren't using the instantiation in your library then what they do doesn't matter.
This is one of the cases where in C++ you simply can't prevent your user from shooting themself in the foot and if they choose to do so the responsibility is on them.
An alias template can not be specialized and has the behaviour you need for class templates.
template<class T>
struct my_class_implementation_which_should_not_be_used_directly
{
// impl
};
template<class T>
using my_class = my_class_implementation_which_should_not_be_used_directly<T>;
In addition you should document that specialising my_class_implementation_which_should_not_be_used_directly results in undefined behavior. Now your libraries user can not specialize my_class accidentally and is warned about the class with the ugly name directly.
Edit:
You can prevent specializations of your templates with enable_if in C++11. This is impractical though.
#include <type_traits>
template<
typename real_t,
typename = typename std::enable_if<
std::is_floating_point<real_t>::value
>::type
>
struct check_t;
template<
typename real_t,
typename = typename
std::enable_if<
std::is_floating_point<real_t>::value,
check_t<real_t>
>::type
>
class vec_t
{
};
#if 1
template<>
class vec_t<int> {};
template<>
class vec_t<int,check_t<int>> {};
#endif
void test()
{
vec_t<float> vecf;
vec_t<int> veci;
}
link
main.cpp:26:16: error: no type named 'type' in 'struct std::enable_if<false, void>'
The best way to prevent such behavior is through coding standards and code review.
You cannot force the compiler into an error in this case (other than using workarounds like those suggested in other answers), because that behavior is actually allowed by the language, although it's real usefulness can be questioned.
The matter is - it is very possible that you want/need to provide a generic behavior for multiple types (hence the use of templates) but you need to provide a specific implementation for some of the allowed types (notably std::string)
A quick & dirty example (it's a function, but the same could apply to classes) could be the following:
template<typename TData> TData GetData(std::string argument)
{
std::stringstream stream;
TData retVal;
stream.str(argument);
stream >> retVal;
return retVal;
}
However this is going to fail with std::string, as the >> operator would stop after the first blank space. So you could provide a dedicated specialization.
template<> std::string GetData(std::string argument)
{
return argument;
}
There are a few ways to go about this. You can declare specific specializations without defining them. eg:
template<> struct MyStruct<int>;
That way, if someone tries to instantiate with an int, they would get this specialization and it won't compile because there is n definition. Then you can write a simple macro to do this for all the types you don't want a specialization for.
For the inverse of this, make the definition empty:
template<typename T> struct MyStruct{};
Then define the specific types you plan to support:
template<> struct MyStruct<int> {...};
template<> struct MyStruct<std::string> {...};
//etc...

Changing deleter for std::unique_ptr

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.

Given a T and function name and type, how can I resolve T::function?

Given an Event struct and an object that implements a function with a specific name and prototype, known by the Event struct, I want to return a pointer or bind to that function. Exactly what it returns doesn't matter; it can just as easily be a pointer-to-member-function or a bind.
It's a bit hard to explain, so here's some psuedo-code:
struct Foo {
void onEvent();
};
struct Bar {
void onEvent();
};
struct Event
{
// I'm not sure what would go here
// Needs something that can be used to resolve T::onEvent, without
// knowing what T is until GetEventFunction is called.
typedef std::function<void()> function_type;
};
template<typename T, typename EventType>
EventType::function_type GetEventFunction(T* object)
{
return std::bind(T::(EventType::Something), object);
}
GetEventFunction<Foo, Event>(new Foo); // Returns Foo::onEvent
GetEventFunction<Bar, Event>(new Bar); // Returns Bar::onEvent
Can this behavior be achieved, or is C++ too limited to allow this?
Please read this before answering
I am not looking for reflection. As far as I'm aware, all of the information needed to do what I'm aiming for is available at compile time.
Also, I am not interested in alternate approaches. I know many ways to achieve this behavior with additional code, such as template specializations for each Event type, but I'm looking for a way to achieve this specifically.
Maybe I didn't explain well, but the function name is unique for each Event type. A FooEvent should resolve T::onFooEvent, while a BarEvent should resolve T::onBarEvent.
C++ can operate on types and values, but not on names. That's dealing with text, which is a macro-level thing that happens before C++ proper gets to look at the code. You can't take the type BarEvent and convert it into the function T::onBarEvent, because there is no association between them except for what they happen to be named.
That's why Luc's answer used a specific name: names of functions have to be hard-coded.
Now, you can side-step C++'s rules a bit via the use of a traits template. For example, you can create an event_traits template type that has a member function which takes T and calls a specific function on it. It would look like this:
template<typename event_type>
struct event_traits
{
template<typename T> void Dispatch(T *t) {t->DefaultEventFunction();}
};
The above uses DefaultEventFunction.
If you want each Event to have its own event function, you'll need a specialization for each Event class. And if you want to enforce this rule, simply never define DefaultEventFunction in any of your T objects; the compiler will complain. Change the name into something unlikely to be used, like WhyDidYouNameThisFunctionLikeThisStopIt.
template<>
struct event_traits<FooEvent>
{
template<typename T> void Dispatch(T *t) {t->onFooEvent();}
};
template<>
struct event_traits<BarEvent>
{
template<typename T> void Dispatch(T *t) {t->onBarEvent();}
};
This is where macros can come in handy:
#define REGISTER_EVENT_HANDLER(eventName)\
template<> struct event_traits<eventName>\
{\
template<typename T> void Dispatch(T *t) {t->on ## eventName ();}\
};
Thus, your GetEventFunction would look like this:
template<typename T, typename EventType>
EventType::function_type GetEventFunction(T* object)
{
return std::bind(event_traits<EventType>::Dispatch<T>, object);
}
If you do have the name of the member, then you don't need to know of a type -- assuming that member is not an overloaded member function.
template<typename T>
auto GetEventFunction(T& object)
-> decltype( std::bind(&T::onEvent, std::ref(object)) )
{ return std::bind(&T::onEvent, std::ref(object)); }
// Usage:
Foo f;
auto event = GetEventFunction(f);
Note that this is somewhat contrived, because the onEvent you mentioned doesn't take any arguments. If it did, you'd need more scaffolding. (I'd recommend writing a mem_fn that also accepts an object, unlike std::mem_fn.)

"What happened to my SFINAE" redux: conditional template class members?

I'm new to writing template metaprogramming code (vs. just reading it). So I'm running afoul of some noob issues. One of which is pretty well summarized by this non-SO post called "What happened to my SFINAE?", which I will C++11-ize as this:
(Note: I gave the methods different names only to help with my error diagnosis in this "thought experiment" example. See #R.MartinhoFernandes's notes on why you wouldn't actually choose this approach in practice for non-overloads.)
#include <type_traits>
using namespace std;
template <typename T>
struct Foo {
typename enable_if<is_pointer<T>::value, void>::type
valid_if_pointer(T) const { }
typename disable_if<is_pointer<T>::value, void>::type
valid_if_not_pointer(T) const { }
};
int main(int argc, char * argv[])
{
int someInt = 1020;
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
return 0;
}
#Alf says what happened to the SFINAE is "It wasn't there in the first place", and gives a suggestion that compiles, but templates the functions instead of the class. That might be right for some situations, but not all. (For instance: I'm specifically trying to write a container that can hold types that may or may not be copy-constructible, and I need to flip methods on and off based on that.)
As a workaround, I gave this a shot...which appears to work correctly.
#include <type_traits>
using namespace std;
template <typename T>
struct FooPointerBase {
void valid_if_pointer(T) const { }
};
template <typename T>
struct FooNonPointerBase {
void valid_if_not_pointer(T) const { }
};
template <typename T>
struct Foo : public conditional<
is_pointer<T>::value,
FooPointerBase<T>,
FooNonPointerBase<T> >::type {
};
int main(int argc, char * argv[])
{
int someInt = 1020;
#if DEMONSTRATE_ERROR_CASES
Foo<int*>().valid_if_not_pointer(&someInt);
Foo<int>().valid_if_pointer(304);
#else
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
#endif
return 0;
}
But if this is not broken (is it?), it's certainly not following a good general methodology for how to turn on and off methods in a templated class based on sniffing the type for traits. Is there a better solution?
Firstly, C++11 did not carry forward boost's disable_if. So if you're going to transition boost code, you'll need to use enable_if with a negated condition (or redefine your own disable_if construct).
Secondly, for SFINAE to reach in and apply to the method level, those methods must be templates themselves. Yet your tests have to be done against those templates' parameters...so code like enable_if<is_pointer<T> will not work. You can finesse this by making some template argument (let's say X) default to be equal to T, and then throw in a static assertion that the caller has not explicitly specialized it to something else.
This means that instead of writing:
template <typename T>
struct Foo {
typename enable_if<is_pointer<T>::value, void>::type
valid_if_pointer(T) const { /* ... */ }
typename disable_if<is_pointer<T>::value, void>::type
valid_if_not_pointer(T) const { /* ... */ }
};
...you would write:
template <typename T>
struct Foo {
template <typename X=T>
typename enable_if<is_pointer<X>::value, void>::type
valid_if_pointer(T) const {
static_assert(is_same<X,T>::value, "can't explicitly specialize");
/* ... */
}
template <typename X=T>
typename enable_if<not is_pointer<X>::value, void>::type
valid_if_not_pointer(T) const {
static_assert(is_same<X,T>::value, "can't explicitly specialize");
/* ... */
}
};
Both are now templates and the enable_if uses the template parameter X, rather than T which is for the whole class. It's specifically about the substitution that happens whilst creating the candidate set for overload resolution--in your initial version there's no template substitution happening during the overload resolution.
Note that the static assert is there to preserve the intent of the original problem, and prevent someone being able to compile things like:
Foo<int>().valid_if_pointer<int*>(someInt);
The way I see it you don't want SFINAE here. SFINAE is useful to pick between different templated overloads. Basically, you use it to help the compiler pick between template <typename Pointer> void f(Pointer); and template <typename NotPointer> void f(NotPointer);.
That's not what you want here. Here, you have two functions with different names, not two overloads of the same. The compiler can already pick between template <typename Pointer> void f(Pointer); and template <typename NotPointer> void g(NotPointer);.
I'll give an example to explain why I think SFINAE is not only unnecessary, but undesirable here.
Foo<int> not_pointer;
Foo<int*> pointer;
not_pointer.valid_if_pointer(); // #1
not_pointer.valid_if_not_pointer(); // #2
pointer.valid_if_pointer(); // #3
pointer.valid_if_not_pointer(); // #4
Now, let's say you managed to get this working with SFINAE. Attempting to compile this piece of code will yield errors on lines #1 and #4. Those errors will be something along the lines of "member not found" or similar. It may even list the function as a discarded candidate in overload resolution.
Now, let's say you didn't do this with SFINAE, but with static_assert instead. Like this:
template <typename T>
struct Foo {
void valid_if_pointer(T) const {
static_assert(std::is_pointer<T>::value, "valid_if_pointer only works for pointers");
// blah blah implementation
}
void valid_if_not_pointer(T) const {
static_assert(!std::is_pointer<T>::value, "valid_if_not_pointer only works for non-pointers");
// blah blah implementation
}
};
With this you'll get errors on the same line. But you'll get extremely short and useful errors. Something people have been asking of compiler writers for years. And it's now at your doorstep :)
You get the same thing: errors on both cases, except you get a much better one without SFINAE.
Also note that, if you didn't use static_assert at all and the implementation of the functions was only valid if given pointers or non-pointers, respectively, you would still get errors on the appropriate lines, except maybe nastier ones.
TL;DR: unless you have two actual template functions with the same name, it's preferable to use static_assert instead of SFINAE.