C++ creating generic template function specialisations - c++

I know how to specialise a template function, however what I want to do here is specialise a function for all types which have a given method, eg:
template<typename T> void foo(){...}
template<typename T, if_exists(T::bar)>void foo(){...}//always use this one if the method T::bar exists
T::bar in my classes is static and has different return types.
I tried doing this by having an empty base class ("class HasBar{};") for my classes to derive from and using boost::enable_if with boost::is_base_of on my "specialised" version. However the problem then is that for classes that do have bar, the compiler cant resolve which one to use :(.
template<typename T>
typename boost::enable_if<boost::is_base_of(HasBar, T>, void>::type f()
{...}
I know that I could use boost::disable_if on the "normal" version, however I do not control the normal version (its provided by a third party library and its expected for specialisations to be made, I just don't really want to make explicit specialisations for my 20 or so classes), nor do I have that much control over the code using these functions, just the classes implementing T::bar and the function that uses it.
Is there some way to tell the compiler to "always use this version if possible no matter what" without altering the other versions?
EDIT: I tried a different approach using a template class and explicit specialisations, but this is apparently also not allowed...Anyway to make this approach work?
template<typename T>class ImpFoo
{
public:
//error C3637: 'foo' : a friend function definition cannot be a specialization of a function template
template<> friend void foo<T>(){...}
};
...
class SomeClass : public ImpFoo<T>
{
...
SomeType bar(){...}
};

Sadly you are out of luck in this situation as descriped, the best thing you can do is to explicitly specialize the templates as #aaa says.
As you can limit these specializations to a simple forwarding to one central function, the overhead for 20 classes should be bearable. E.g.:
template<class T> my_foo() { /* do the actual work */ }
template<> void foo<MyClass01>() { my_foo<MyClass01>(); }
// ...
template<> void foo<MyClass20>() { my_foo<MyClass20>(); }

Related

Building a variadic template class with a set of function overloads based on the template arguments?

Motivation: I need to build a base class for a C++17 library that will have overloads for a virtual function based on types that the user identifies at compile time. Basically, when a particular overload of the function is called on the base class, I want to make sure the correct version is called in the derived class. My initial instinct was to build a virtual template function, but of course C++ cannot allow this because the compiler will not know what versions of it to put in the virtual function table. Since I will know all of the types at compile time, however, is it possible to make the base class itself a variadic template and use the template arguments to build the set of overloaded version of the virtual function that would be needed?
Fold expressions are right out because they can't be used to declare functions. Recursive templates seem promising, but I worry that having a long chain of inheritance for the base class will create a performance hit. Here's the working code that I have:
template <typename... Ts> class MyClass;
template <typename T, typename... Ts>
struct MyClass<T, Ts...> : public MyClass<Ts...> {
using MyClass<Ts...>::MyFunction;
virtual bool MyFunction(T in) { return true; }
};
template <>
struct MyClass<> {
virtual bool MyFunction(...) { return false; }
};
Should this technique be sufficient? Or does anyone have other ideas on how I might accomplish this goal?
My other ideas include:
Cap the number of template arguments that can be handled and enable-if each overload based on whether the argument list is long enough to include it. Downside: this technique would be an arbitrary limit on the number of types.
Use a variadic macro to build the class. Downside: This technique would be confusing and inelegant.
Create a function to assign a type to an ID number in the base class, pass it to the derived class as a void * with its id, and translate it back at that point to make the appropriate overloaded call. Downside: this technique would be tricky to keep type safe and to minimize the amount of work the end-user needs to do.
Right now I'm leaning toward implementing the first of these alternatives and doing some performance testing to compare it to my working version, but would love if there is something cleaner that I'm missing.
Your implementation is right for C++14.
C++17 allows variadic using, to avoid recursion:
template <typename T>
struct MyClassImpl
{
virtual ~MyClassImpl() = default;
virtual bool MyFunction(T in) = 0; // or { return true; }
};
template <typename... Ts>
struct MyClass : public MyClassImpl<Ts>...
{
using MyClassImpl<Ts>::MyFunction...;
};
Demo

How do I define methods outside of the declaration for my specialization of a non-type template class?

The title is a mouthful, but basically I wrote something like this:
enum EnumType{ValA, ValB};
template<EnumType> class A {};
template<>
class A<ValA>
{
private:
double param;
public:
A(double param);
};
template<>
A<ValA>::A(double param)
{
// Do Stuff
}
and when I try to compile it I get:
error: template-id 'A<>' for 'A<(EnumType)0u>::A(double)' does not
match any template declaration
Am I doing this wrong?
After searching online for similar cases, I tried to remove template<> (even though I don't understand why this would work), but then I get
multiple definition of 'A<(EnumType)0u>::A(double)'
I guess that I can replace template<> by inline (I tried and it compiles), but that doesn't feel like the proper way to do it (or if it is, I don't understand why).
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
The standard says:
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
Therefore, in your case you must use:
A<EnumType::ValA>::A(double param)
{
// Do Stuff
}
No template<> at all is just fine. That's because you are actually specializing a (special) member function (the constructor) of an explicitly specialized class template.
See it on coliru.
It would have been different if no explicit specialization was given.
As a minimal working example:
enum EnumType{ValA, ValB};
template<EnumType> class A
{
private:
double param;
public:
A(double param);
};
template<>
A<EnumType::ValA>::A(double)
{
// Do Stuff
}
int main() {
A<EnumType::ValA> a{0.};
}
In this case, template<> is required before the definition of the constructor because you are not defining a specialization of a member function of an already specialized class template.
You missed a semicolon (;) at the the end of class definition.
And the non template member function can be defined this way:
A<ValA>::A(double param) {
// Do Stuff
}
Informally, the template parameter list is only written when necessary, for example, for defining a member function template of a class template, the two template parameter list should all be written
template<class U, class V>
class A{
template <class T>
A();
};
template<class U, class V>
template <class T>
A<U, V>::A() {}
and a empty template parameter list is needed for a explicit specialisation of function template (which, i guess, is the reason why you use so here), informally because it tells the compiler that this is not a function overloading.

Stringify and Unstringify template arguments

suppose I have a lot of classes with their "*Pack" counterparts in naming. For example, if I have a class Moo, I have MooPack, if I have Foo, I also have FooPack.
I want to have a c++ templated function which returns a FooPack from a Foo
template <class X, class XPack>
XPack packify(X input){
...
}
Is it possible to do this without having to specify the template argument? At the moment, this has to be done like the following:
Moo moo;
MooPack mooppey = packify<Moo, MooPack>(moo);
If it only required the Moo template argument, that ugly template specification bit could go away, but apart from using #defines, which isn't really the best solution either, still doesn't do it.
Is there a way, or will I have to wait for c++0x?
You don't have to specify Moo, just MooPack, because moo will deduce the argument for you. However, I'd suggest that you make MooPack a typedef or nested class (called Pack) inside Moo itself, in which case you can easily access it by typename X::Pack inside the template.
class Moo {
public:
class Pack {
...
};
};
template<typename T> typename T::Pack packify(T t) {
...
}
// usage
Moo m;
Moo::Pack p = packify(m);
As the answer by DeadMG already mentioned you don't need to explicitely specify the parameter type as it can be deduced automaticaly (if it's the second instead of the first template parameter). Since you said you can't change the type declarations to form a link between the classes, I would propose the traits route for that (think std::iterator_traits):
template<typename T> struct pack_traits;
template<> struct pack_traits<Moo> { typedef MooPack Pack; };
...//traits for other packifable classes
template<typename T> pack_traits<T>::Pack packify(T val){...}
...
Moo moo;
MooPack mooppey = packify(moo);
This way you can call the function without manually specifying template arguments, without needing to modify the classes themselves.

How to intentionally cause a compile-time error on template instantiation

Sometimes when coding with C++ templates, you want to prevent users from instantiating a specific specialization or set of specializations, because the result would be nonsensical. So you can define a (specific or partial) specialization whose definition, if instantiated, would cause a compiler error. The goal would be, if a user "misuses" the template, to cause a compiler error right next to a comment in your header file explaining what not to do, rather than leaving the compiler to come up with some confusing error message by its own devices, or maybe allowing the questionable code to compile.
Example:
template <typename T> struct MyClassTemplate {
// ...
};
template <typename T> struct MyClassTemplate<T*> {
// Do not use MyClassTemplate with a pointer type!
typedef typename T::intentional_error err;
};
There are a number of ways to do this (depending on whether your specialization is a complete or partial specialization of a class or function). But the syntax used must (?) depend on a template parameter, or else the compiler will complain when it first parses the intentional-error definition. The example above has a hole in that somebody could stubbornly define an intentional_error nested type or member typedef (though I'd say they would then deserve whatever problems come up as a result). But if you use a trick too fancy, you're likely to get an indecipherable and/or misleading compiler error message, which mostly defeats the purpose.
Are there better straightforward ways to disallow template instantiations?
I'm aware that in C++0x, template Concepts and deleted function declarations will provide much better control over this sort of thing, but I'm looking for answers that are valid C++03.
You could just omit defining it.
template <typename T> struct MyClassTemplate<T*>;
You could also derive from a non-defined specialization
template <typename T> struct invalid;
template <typename T> struct MyClassTemplate<T*> : invalid<T> { };
Note that explicit specializations that declare classes or functions will never depend on template parameters. So, stuff like this that depend on template parameters can't work anyway. In that case, declaring a non-defined explicit specialization should be sufficient
template<> struct MyClassTemplate<int*>;
For me this sounds like a typical case for static_assert from C++0x or BOOST_STATIC_ASSERT. The static_assert functionality has the advantage that you can pass a custom error message so that the reason for the error is more clear.
Both ways are giving you the opportunity to prematurely end the compilation process under some custom defined compile time condition.
with static_assert:
template <typename T> struct MyClassTemplate<T*> {
static_assert(always_false<T>::value, "Do not use MyClassTemplate with a pointer type!");
};
with BOOST_STATIC_ASSERT
template <typename T> struct MyClassTemplate<T*> {
// Do not use MyClassTemplate with a pointer type!
BOOST_STATIC_ASSERT(always_false<T>::value);
};
Always false would look something like this:
template< typename T >
struct always_false {
enum { value = false };
};
HTH
Edit: Fixed the examples to make them actually work ;-) Thanks to GMan!
If you don't want to use a library, this construct is pretty reliable (it's roughly what Boost does internally):
template <typename T>
void must_be_specialized(T const&)
{
enum dummy { d = (sizeof(struct must_be_specialized_for_this_type)
== sizeof(T)) };
}
You can put something analogous in a specialization to disallow instantiation of the template with that type. I wouldn't, personally, worry about must_be_specialized_for_this_type gaining a definition from somewhere, but you could use a forward declaration to squirrel it away in a private namespace if you really wanted.
Concepts were removed from '0x. You can use a library, like Boost Concept Check.
"Are there better straightforward ways to disallow template instantiations?" Nothing significantly better than what you have already identified. I am pretty sure C++ protection mechanisms are there to protect you from accident not from malice. And someone defining a specialisation or a class to break your intended use I would consider malicious. Perhaps you could hit the person in the back of the head each time they do it.
I personally prefer to put the checks into templates that exist only to describe the checks. That allows interesting combinations of inheritance and templates.
template <class T>
class not_with_pointer_t { };
template <class T>
class not_with_pointer_t<T*>;
template <class T>
class some_class_t : public not_with_pointer_t<T> { };
template <class T, template <class U> class base_t>
class another_class_t : public base_t<T> { };
typedef some_class_t<int> a_t; // ok
typedef some_class_t<void*> b_t; // error if instantiated
typedef another_class_t<void*, not_with_pointer_t> c_t; // error if instantiated
template <class T> class unrestricted_t { };
typedef another_class_t<void*, unrestricted_t> d_t; // ok
boost::enable_if

Where can I find, or how can I create an elegant C++ member function template wrapper mechanism without resporting to boost?

I want to be able to templatize a class on a member function without needing to repeat the arguments of the member function -- i e, derive them automatically.
I know how to do this if I name the class based on how many arguments the function takes, but I want to derive that as well.
Something like this, although this doesn't work (at least in MSVC 2008 sp1, which is my target compiler):
class Foo {
void func0();
int func2(char *, float);
};
template<typename T> class Wrapper;
// specialize for zero-argument void func
template<typename Host, void (Host::*Func)()> class Wrapper<Func> : public Base {
... specialization goes here ...
};
// specialize for two-argument value func
template<typename Host, typename Ret, typename Arg0, typename Arg1, Ret (Host::*Func)(Arg0, Arg1)> class Wrapper<Func> : public Base {
... specialization goes here ...
};
Through "Base" I can then treat these polymorphically. In the end, I want to use this to create a simple wrapper syntax for a scripting language:
WrapClass<Bar> wrap(
MemberFunction<&Bar::func0>("func0") +
MemberFunction<&Bar::func2>("func2")
);
However, that doesn't work: the specialization syntax is wrong, because you can't match a function pointer to a typename argument.
I believe you'll need to take a traits approach, the most common library of which is boost's, but if you wanted to avoid boost, it wouldn't be extremely difficult to roll your own if you limited the scope of the implementation to just pointer-to-member-functions and the traits on those you need (modern c++ design is a great book explaining the theory). Here's how I would do it with boost's function_traits and enable_if.
You could use a generic template argument, enable_if it for function pointers, then use function types (or type traits) to pull out out the information you need:
#include <boost/function_types/function_arity.hpp>
#include <boost/function_types/is_member_pointer.hpp>
template<typename T, class Enable = void> class Wrapper;
/* other specializations... */
// For member functions:
template <class T>
class Wrapper<T, typename enable_if<is_member_pointer<T> >::type>
{ /* function_arity<T>::value has the number of arguments */ };
See this and this
The C++ standard library provides mem_fun_ref which sort of works how you want, though it only works for nullary and unary functions. Of course, you can use a struct with all the parameters as your one argument.