Template class + virtual function = must implement? - c++

This code:
template <typename T>
struct A
{
T t;
void DoSomething()
{
t.SomeFunction();
}
};
struct B
{
};
A<B> a;
is easily compiled without any complaints, as long as I never call a.DoSomething().
However, if I define DoSomething as a virtual function, I will get a compile error saying that B doesn't declare SomeFunction. I can somewhat see why it happens (DoSomething should now have an entry in the vtable), but I can't help feeling that it's not really obligated. Plus it sucks.
Is there any way to overcome this?
EDIT 2: Okay. I hope this time it makes sence:
Let's say I am doing intrusive ref count, so all entities must inherit from base class Object. How can I suuport primitive types too? I can define:
template <typename T>
class Primitive : public Object
{
T value;
public:
Primitive(const T &value=T());
operator T() const;
Primitive<T> &operator =(const T &value);
Primitive<T> &operator +=(const T &value);
Primitive<T> &operator %=(const T &value);
// And so on...
};
so I can use Primitive<int>, Primitive<char>...
But how about Primitive<float>? It seems like a problem, because floats don't have a %= operator. But actually, it isn't, since I'll never call operator %= on Primitive<float>.
That's one of the deliberate features of templates.
If, for some reason, I would define operator %= as virtual. Or, if i'll pre-export Primitive<float> from a dll to avoid link errors, the compiler will complain even if I never call operator %= on a Primitive<float>. If it would just have fill in a dummy value for operator %= in Primitive<float>'s vtable (that raises an exception?), everything would have been fine.

Put the virtuals into selectable base classes...
struct Jumper
{
virtual void Jump =0;
};
struct Crawler
{
virtual void Crawl() =0;
};
struct JumperCrawler:
public Jumper,
public Crawler
{
};
template<typename T, typename Methods>
class ICanBoostJumpingAndCrawling :
public Methods
{
T t;
};
Now you can use ICanBoostJumpingAndCrawling with Jumper,Crawler or JumperCrawler supplied as the Methods template parameter; realizing that you need to be derived from it so that you can implement Jumping and or Crawling in a subclass.
FYI, This makes the name "ICanBoostJumpingAndCrawling" completely misleading because it may or may not be able to do that; which means it should be renamed to something like "Booster".

That's not a bug, it's a feature -- seriously. At one time, most compilers would NOT compile the code, for exactly the reason you give. They've since been updated to compile it, partly because the standard requires it.
There was feature called "Concepts" in the C++ 0x standard for quite a while that would have allowed you to specify that T needed a member named 'SomeFunction', including its return type, argument type(s), etc.
Sadly, at the last meeting of the standard committee, they decided finishing up Concepts would delay the standard longer that most people wanted to wait, so they removed them.
Though it's not nearly as good, Boost does have a Concept Checking library that can do what you're asking about.

One way to overcome this is to specialize A for template argument B and not declare DoSomething()
template <>
struct A<struct B>
{
T t;
};
Ofcourse this means that you now have to implement the entire A struct from scratch.

So the compiler should be able to work out within the compilation unit just what is in use. As soon as you start to involve multiple compilation units it no longer has the limited scope and takes the necessary step to ensure that all of the class can compile.
For exporting from a library don't force the pre export, you can ignore the warnings about not exporting the templates as long as you compile all the code with the same compiler the template will be compiled the same in all locations, only compile what is necessary within each compilation unit.
To work around the problem with virtual, then the best you can do is to defer the issue to some other class - don't put virtual in the template.
Perhaps
addition of a 'traits' portion to your template would allow a cheap way out.
use multiple inheritance to define the composite template, like using shims
ie.
template <typename T>
class Additive
{
public:
Primitive<T> &operator =(const T &value);
Primitive<T> &operator +=(const T &value);
};
template <typename T>
class Multiplicative
{
public:
Primitive<T> &operator *=(const T &value);
Primitive<T> &operator /=(const T &value);
};
template <typename T>
class Integers : public Additive<T>, public Multiplicative<T>;
I'd really go back and ask if your abstracting the right level of information for making the template.

Related

MSVC is happy with this code but GCC isn't so keen

This code compiles in MSVC (19.00.23918) but GCC doesn't like it unless I use this-> access to member operator when I call Detach_Internal().
Is GCC catching a potential bug here that MSVC isn't? As a general rule is it a better idea to use this-> at all times when referencing functions in base classes?
Note GCC will compile it with -fpermissive.
#include <memory>
namespace Events
{
template<typename T>
class EventBase
{
protected:
void Detach_Internal(std::weak_ptr<void> const & p)
{
}
};
template<typename T>
class Event : public EventBase<T>
{
public:
void Detach(std::weak_ptr<void> const & p)
{
Detach_Internal(p);
}
};
}
int main(void)
{
auto event = std::make_unique<Events::Event<void()>>();
}
33:30: error: there are no arguments to 'Detach_Internal' that depend on a template parameter, so a declaration of 'Detach_Internal' must be available [-fpermissive]
Is GCC catching a potential bug here that VS isn't? As a general rule is it a better idea to use this-> at all times when referencing functions in base classes?
GCC is correct. You should add this-> when referring names in dependent base class (i.e. EventBase<T>, which depends on template parameter T).
Otherwise as a nondependent name, Detach_Internal won't be looked up in dependent base class EventBase<T>.
To solve the issue you can make the name Detach_Internal dependent, then it will be looked up at the time of instantiation, at that time the exact base class template specialization is fixed. e.g.
this->Detach_Internal(p);
EventBase<T>::Detach_Internal(p);
using EventBase<T>::Detach_Internal;
Detach_Internal(p);

MSVC allows use of incomplete/undeclared types inside of template class method bodies?

I recently reopened a visual studio project I last worked on a year ago, and I want to get it to compile under g++. Among other issues, the compiler complains about some template code that doesn't appear legal in the first place.
Specifically, some of the template class method's instantiate Iterators for their class that are defined lower down, with no forward declarations. This would not be a problem if I was not working with templates, because the class declarations themselves are perfectly legal; it's the method bodies, which would ordinarily be in source files, which are causing problems. It seems as though templates compile differently to account for this, at least under msvc.
Sample code:
template<class T>
class ClassA : public HasIterator<T>
{
public:
Iterator<T> * GetIterator()
{
return new ClassAIterator<T>(this);
}
};
template<class T>
class ClassAIterator : public Iterator<T>
{
ClassA *foo;
public:
AggregateWrapperIterator(ClassA *foo)
{
//...
}
bool HasNext()
{
//..
}
T Next()
{
//..
}
};
I'd just add forward declarations but it get's complicated because of inheritance (there was a reason I set it up this way in the first place).
My question is this: for what reason does msvc allow this code, and does g++ have similar support?

pimpl for a templated class

I want to use the pimpl idiom to avoid having users of my library need our external dependencies (like boost, etc) however when my class is templated that seems to be impossible because the methods must be in the header. Is there something I can do instead?
If the class is templated, your users essentially need to compile it (and this is literally true in the most widely-used C++ implementations) and so they need your external dependencies.
The simplest solution is to put the bulk of your class's implementation in a non-template base class (or encapsulated member object of some class). Solve the module-hiding problem there.
And then write the template derived (or enclosing) class to add type safety to it.
For example, suppose you have a template that provides the amazing ability to allocate on first access (omitting the necessary copy constructor, assignment, destructor):
template <class T>
class MyContainer
{
T *instance_;
public:
MyContainer() : instance_(0) {}
T &access()
{
if (instance_ == 0)
instance_ = new T();
return *instance_;
}
};
If you wanted the "logic" to be separated into a non-template base class, you'd have to parameterise the behaviour in the non-template way, which is to say, use virtual functions:
class MyBase
{
void *instance_;
virtual void *allocate() = 0;
public:
MyBase() : instance_(0) {}
void *access()
{
if (instance_ == 0)
instance_ = allocate();
return instance_;
}
};
Then you can add the type-awareness in the outer layer:
template <class T>
class MyContainer : MyBase
{
virtual void *allocate()
{ return new T(); }
public:
T &access()
{ return *(reinterpret_cast<T *>(MyBase::access())); }
};
i.e. You use virtual functions to allow the template to "fill in" the type-dependent operations. Obviously this pattern would only really make sense if you have some business logic that is worth the effort of hiding.
You can explicitly instantiate templates in the source file, but that is possible only if you know what the template type is going to be. Otherwise, do not use pimpl idiom for templates.
Something like this :
header.hpp :
#ifndef HEADER_HPP
#define HEADER_HPP
template< typename T >
class A
{
// constructor+methods + pimpl
};
#endif
source.cpp :
#include "header.hpp"
// implementation
// explicitly instantiate for types that will be used
template class A< int >;
template class A< float >;
// etc...
There are two general solutions:
while the interface depends on some type T, it defers to a more weakly typed implementation (e.g. one using void* pointers directly or trough type erasure), or
you support only a specific and quite limited number of types.
The second solution is relevant for e.g. char/wchar_t-dependent stuff.
The first solution was quite common in the early days of C++ templates, because at that time compilers were not good at recognizing commonalities in the generated machine code, and would introduce so called “code bloat”. Today, much to the surprise of any novice who tries it out, a templated solution can often have smaller machine code footprint than a solution relying on runtime polymorphism. Of course, YMMV.
Cheers & hth.,

Where/how to define a template

What is the best pratice in regards to defining a template in C++?
template <class T>
class A
{
private:
// stuff
public:
T DoMagic()
{
//method body
}
}
Or:
template <class T>
class A
{
private:
// stuff
public:
T DoMagic();
}
template <class T>
A::T DoMagic()
{
// magic
}
Another way?
I seem to stumble over some controversy regarding this subject.
So; What path to choose?
This is completely a matter of style. That said however:
choose a way and stick to it -- either all inline, or all out, or mixed based on some rule
personally I use a 3 line rule. If the method body in the template is longer than 3 lines I move it outside.
There's no real reason not to include all definitions inline (they are inline from the compilers POV anyway), however, many people argue that keeping them separate is more clean, and allows the class definition to be more readable.
Use an increasing level of separation as the templates you write grow larger and more complex.
Performance will be the same no matter how you separate the definitions from the declarations, so your main concern here should be readability and maintainability.
When writing a simple template used only in one place, declare and define it inline with the declarations right in the CPP file where you're going to use it. There's no reason to force a global recompile if only one block of code needs this template.
file.cpp
template<class Gizmo> bool DoSomethingFancy()
{
// ...
}
For small template utilities used across translation units, define and declare them together in an H file:
utility.h
template<class Gizmo> bool DoSomethingUseful()
{
// ...
}
As your templates become more complex it will become more important to be able to view the declaration separately from the definition. At first, keep everything separate but in the same file:
utility.h
template<class Type> class Useful
{
bool FunctionA();
bool FunctionB();
};
template<class Type> bool Useful<Type>::FunctionA()
{
// ...
}
template<class Type> bool Useful<Type>::FunctionB()
{
// ...
}
But eventually even this will become unwieldly. When it does, separate it in to a header file for the declarations, and an INC file for the definitions. At the end of the header file, #include the INC file:
utility.h :
template<class Type> class MoreUseful
{
bool FunctionA();
bool FunctionB();
};
#include "utility.inc"
utility.inc :
template<class Type> bool MoreUseful<Type>::FunctionA()
{
// ...
}
template<class Type> bool MoreUseful<Type>::FunctionB()
{
// ...
}
This is a religious (style) issue. I prefer to define my functions outside of the template declaration for classes that have more than one method or the few methods are simple.
In either case, my understanding is that the template declaration and the method definitions must be in the same translation unit. This is because the template is more like a stencil, the compiler plugs a given type into the stencil and generates code for the given type.
Whatever you decide, just be consistent.
I usually define all the methods outside but each time I wish C++ had some sort of "template blocks":
template <class T>
struct A
{
T foo();
T bar(T * t);
T baz(T const & t);
};
template <class T> // Made-up syntax
{
T A::foo()
{
//...
}
T A::bar(T * t)
{
//...
}
T A::baz(T const & t)
{
//...
}
}
If the functions are non-trivial (i.e. more than one or two lines), consider defining them separately. This makes the interface of the class much easier to navigate, read and understand for the users of your class, who most likely shouldn't have to look at the actual implementation of each method.
For a one-off instance like your example, it makes little difference.
What happens when there are lots of templates with lots of variations? It then helps to put similar types of apples together, and similar types of oranges together away from them. Of course, this must all be done as intuitively as practical. That is greatly affected by the culture of programmers working with the code.

Inheriting from a virtual template class in C++

How do I inherit from a virtual template class, in this code:
// test.h
class Base {
public:
virtual std::string Foo() = 0;
virtual std::string Bar() = 0;
};
template <typename T>
class Derived : public Base {
public:
Derived(const T& data) : data_(data) { }
virtual std::string Foo();
virtual std::string Bar();
T data() {
return data_;
}
private:
T data_;
};
typedef Derived<std::string> DStr;
typedef Derived<int> DInt;
// test.cpp
template<typename T>
std::string Derived<T>::Foo() { ... }
template<typename T>
std::string Derived<T>::Bar() { ... }
When I try to use the DStr or DInt, the linker complain that there are unresolved externals, which are Derived<std::string>::Foo() and Derived<std::string>::Bar(), and the same for Derived<int>.
Did I miss something in my code?
EDIT:
Thanks all. It's pretty clear now.
You need to define template<typename T> std::string Derived<T>::Foo() { ... } and template<typename T>
std::string Derived<T>::Bar() { ... } in the header file. When the compiler is compiling test.cpp it doesn't know all the possible values of T that you might use in other parts of the program.
I think there are some compilers that have connections between the compiling and linking steps that notice references to missing template instantiations and go instantiate them from the .cpp file where they are declared. But I don't know which they are, and the functionality is exceedingly rare to find.
If you define them in the header file most compilers will emit them as a 'weak' symbol into every compilation unit in which they're referenced. And the linker will toss out all except for one definition of the weak symbol. This causes extra compilation time.
Alternately, there are syntaxes for explicitly instantiating templates and forcing the compiler to emit definitions right there. But that requires you to be aware of all the values T could possibly have and you will inevitably miss some.
You have to ensure that the member functions are instantiate for all the required types somewhere.
Usually this is accomplished by defining template functions inline in the header file where they are declared so that any use of the functions will cause them to be instantiated.
As an alternative, you can use explicit instantiations in the source file where you define them but this does require you to know in advance all the types that your template will ever be instantiated for.
This doesn't really have much to do with derivation. It's just a general rule with templates: with most compilers (anything but Comeau) you have to put the full implementation of a template where it's visible in every translation unit that will instantiate that template -- normally in the header.
Even with Comeau, you have to use the export keyword to make things work right. Since They're the only ones that implement export, chances are pretty good that you don't care much though.