I am working on a fairly tightly coupled library which up until now has explicitly assumed all computations are done with doubles. I'm in the process of converting some of the core classes to templates so that we can start computing with std::complex<double>. I've templated about 10 of our classes so far have noticed a tendency toward proliferation of templates. As one class becomes templated, any other class that uses the templated class appears to need templating as well. I think I can avoid some of this proliferation by defining abstract base classes for my templates so that other classes can just use pointers to the abstract class and then refer to either a double or std::complex<double> version of the derived class. This seems to work on at the header level, but when I dive into the source files, the templated class will often have functions which compute a value or container of values of type double or std::complex<double>. It seems like a waste to template a whole class just because a couple of lines in the source file are different because of some other classes return type.
The use of auto seems like a possible way to fix this, but I'm not 100% sure it would work. Suppose I have an abstract base class AbstractFunction from which Function<Scalar> derives, where Scalar can be double or std::complex<double>. Now suppose we have two member functions:
virtual Scalar Function<Scalar>::value(double x);
virtual void Function<Scalar>::values(std::vector<Scalar> &values, std::vector<double> x);
And suppose I have some other class (that I don't want to template) with a member function that calls one of these.
// populate double x and std::vector<double> xs
auto value = functionPtr->value(x);
std::vector<auto> values;
functionPtr->values(values, xs);
// do something with value and values
where functionPtr is of type std::shared_ptr<AbstractFunction>.
I could see auto working for the first case, but I don't believe I could construct a vector of auto to be filled with the second one. Does this necessitate making the calling class a template? Can someone recommend another strategy to cut down on the proliferation of templates?
I think you are already wrong in assuming that the first use-case is going to work. If you have an abstract base class, then either value is a member of it and you can call it through std::shared_ptr<AbstractFunction> or value is not a member of it and only available if you know the derived class' type. In the first case, the AbstractFunction::value method must have a fixed return type, it can not depend on Scalar, which is the template parameter of the derived class.
That said: In my experience the two concept often don't mix well. You either want to create an abstract base class with the full interface or you want a template. In the latter case, there is often no need / no benefit for having an abstract base class. It then follows that also the code using your template works with templates.
What might help you is to "export" the template parameter from Function, i.e.
template<typename T>
class Function
{
public:
using value_type = T;
value_type value() const;
// ...
};
and in other parts of the code, use a template which takes any T which behaves like Function if you don't want to directly write out (and limit yourself) to Function:
template<typename T>
void something( const std::shared_ptr<T>& functionPtr )
{
// ignoring where x comes from...
using V = typename T::value_type;
V value = functionPtr->value(x);
std::vector<V> values;
functionPtr->values(values, xs);
}
Note that this is just one option, I don't know if it is the best option for your use-case.
Related
I am somewhat new to templates and I don't understand how the compiler derives the templates for child classes when I inherit from the base class in a way where I set the templates.
I am creating a genetic algorithm base class for which I have written an abstract base class for the individuals of a population. I want to have a general definition so I use templates to define the fenotype and genotype:
template<typename T, typename S>
class individual {
public:
individual(S& fenotyp, T& genotyp) :
fenotype(fenotyp), genotype(genotyp) {}
...
S fenotype;
T genotype;
...
};
When the individuals are bitstrings, I have the following child class:
class bitstring_individual : public individual<boost::dynamic_bitset<>,
boost::dynamic_bitset<>> {
public:
using individual::individual;
...
};
Now I no longer have to work with template brackets anymore. Further down the line, I have a function that given a population std::vector<individual<T,S>>, returns the half with the highest fitness. This works on any type of individual so we can keep the definition general:
template<typename T, typename S>
std::vector<individual<T,S>> select_best_half(std::vector<individual<T,S>> parents,
std::vector<individual<T,S>> children) {
...
}
However, if I call this function I get error: no matching function for call to select_best_half(...) and the compiler says template argument deduction/substitution failed: and mismatched types ‘individual<T, S>’ and ‘bitstring_individual'.
In the definition of bitstring_individual we see that:
bitstring_individual : individual<boost::dynamic_bitset<>,boost::dynamic_bitset<>>
so why does the compiler not understand that the templates should be boost::dynamic_bitset<>? Can someone help me understand how the compiler tackles this inheritance and how can I fix it?
(using bitset = boost::dynamic_bitset)
Your bitstring_individual is not the same as individual<bitset, bitset>, and the compiler rightfully does not recognize them as such. One inherits the other, yes, but that does not make them interchangeable everywhere - in particular when used as template arguments.
In short: vectors (and other containers) of different (even polymorphically related) types are not covariant. Just like you cannot pass a std::vector<int> to a function expecting a std::vector<long> you cannot pass a std::vector<bitstring_individual> where a std::vector<individual<bitset, bitset>> is expected.
Note: Yes, they are different conversions, but the idea is the same.
Imagine that sizeof(individual<bitset, bitset>) = 32 and that bitstring_individual adds some members so that sizeof(bitstring_individual) = 48. If the compiler deduced T = S = bitset, then it would generate a method signature containing std::vector<individual<bitset, bitset>>, so a vector whose elements have size 32. But when you try to call it, you are passing a vector whose elements have size 48. Those vectors are not covariant, which would invariably lead to problems.
If you want your concrete individuals to have no other functionality than what the templated base class provides, just do this:
using bitstring_individual = individual<bitset, bitset>;
Otherwise, your vectors cannot store the individuals directly - you would have to use something like std::vector<std::shared_ptr<individual<T, S>>> (alternatively unique_ptr or ref instead of shared_ptr) for all population vectors.
Your question actually deals with covariance and contravariance of (certain) types in C++. Even if you were to "hard-code" your template parameters, i.e. have:
using i_bs_bs = individual<bitset, bitset>;
using std::vector;
class bitstring_individual : public i_bs_bs { ... };
vector<bsi> select_best_half(vector<i_bs_bs> parents, vector<i_bs_bs> children) {
...
}
You'd still get an error passing a vector<bitstring_individual> to select_best_half(). Why? Because, in C++ std::vector<T> is not a covariant type constructor.
To take the the example from the linked-to Wikipedia page, Suppose your inheriting classes were Animal (base class) and Cat (derived class). In C++, you can't add an Animal to a vector of Cats. All elements of that vector need to be Cats. Similarly, and as #MaxLanghof's answer explains, you can't add a bitstring_individual to a vector whose elements are of bitstring_individual's base type. Any special behavior necessary for handling bitstring_individual would simply not apply to the elements of a vector<i_bs_bs>.
I'm pushing IMO the limits of C++template programming. The system is an Arduino but my attempt is applicable to any microcontroller system.
I define Pins using a template class with an 'int' parameters
template<const int pin>
struct Pin {
Pin() { mode(pin, 0); }
};
template<const int pin>
class PinOut : public Pin<pin> {};
I can create template classes to use PinOut like:
template<typename F>
class M {
public:
M() { }
F mF;
};
M<PinOut<1>> m1;
template<int F>
class N {
public:
N() { }
Pin<F> mF;
};
N<1> n1;
But I'd like to not use templates in the classes that use PinOut. This is illustrative of my thinking showing possible approaches but clearly doesn't work.
class R {
public:
R(const int i) {
}
PinOut<i> mF; // create template instance here
};
R r1(1); // what I'd like to able to do
I recognize the problem is creating a type inside class R.
The other possibility is instantiating a PinOut variable and passing it in but again passing and creating a type inside the class is a problem. Something like this:
class S {
public:
S(PinOut<int>& p) { } // how to pass the type and instance
PinOut<p>& mF; // and use it here
};
PinOut<1> pp;
S s1(pp);
Sorry if this sound abrupt but please don't ask why or what I'm trying to do. This is an experiment and I'm pushing my understanding of C++ especially templates. I know there are other approaches.
Yes, any function that takes that type must itself be a template.
But is the entire family of Pin related in a way that some thing are meaningful without knowing T? This can be handled with a base class that's a non-template. The base class idea is especially handy because it can contain virtual functions that do know about T. This lets you switch between compile-time and run-time polymorphism on the fly as desired. Taken to an extreme, that becomes the weaker idea with the same syntax of "Generics" as seen in Java and .NET.
More generally, this is a concept known as type erasure. You might search for that term to find out more. It is designed into libraries in order to keep common code common and prevent gratuitous multiplication of the same passage though multiple instantiations.
In your case, pin is a non-type argument, which is something Generics don't even do. But it may not really affect the type much at all: what about the members change depending on pin? This might be an array bound, or a compile-time constant used to provide compile-time knowledge and optimization, or there for the sole purpose of making the type distinct.
All of these cases are things can be dealt with at run-time, too. If it's for the sole purpose of making the type distinct (e.g. make the compiler check that you pass time values and distance values to the correct parameters) then the real guts are all in a base class that omits the distinctiveness.
If it's an array bound or other type difference that can be managed at run-time, then again the base class or an adapter/proxy can do it at run-time. More generally a compile-time constant that doesn't affect the class layout can be known at run-time with the same effect, just less optimization.
From your example, that it is sensible to make the pin a constructor argument, the class could be implemented in the normal way with run-time configuration. Why is it a template? Presumably for compile-time checking to keep separate things separate. That doesn't cause them to work in different ways, so you want that compile-time part to be optional. So, this is a case where a base class does the trick:
class AnyPin
{
public:
AnyPin (int pin); // run-time configuration
};
template <int pin>
class Pin : public AnyPin { ⋯ };
Now you can write functions that take AnyPin, or write functions that take Pin<5> and get compile-time checking.
So just what does pin do to the class, in terms of its layout and functionality? Does it do anything that makes it unacceptable to just implement it as a run-time constructor value?
You ask that we don't inquire as to what you're trying to do, but I must say that templates have certain features and benefits, and there must be some reason for making it a template. Speaking simply in language-centric terms, did I miss something with the above analysis? Can you give a C++-programming reason for wanting it to be a template, if my summary didn't cover it? That may be why you didn't get any answers thus far.
I want to have a class that holds a data member whose type can vary. Something like:
struct container
{
void push( auto x );
private:
auto m_x;
};
Where the type isn't known until I call push(). How would I do this?
template<typename T>
struct container
{
void push(T x);
private:
T m_x;
};
In C++, it's not possible to implement a class that holds a data member whose type can vary.
Depending on your exact needs, the following solutions come close:
Implement a class template. Instantiate the class template to get the
class you need.
Use a pointer or a reference as data member.
Both solutions fall short in one way or the other; it depends on the exact problem which one is better suited.
You could try boost::any, which lets you store any type but the later retrieval and use must be aware of the actual type (it may try a specific type, work through a list of potential types...).
If you may need to store any type but later during retrieval only need to perform certain operations on the value (for example, streaming the value to a std::ostream, adding it to another such value, ...), you can capture those operations as pointers to function template instantiations, or by instantiating a class template in which the operations are overrides of base class methods, such that your container can store a pointer to the base class and dispatch using runtime polymorphism.
I have got two classes.
The first class (A) is builded with an template.
template <class T>
class A
{
public:
T value;
};
The second class (B) should have an object of class A as member variable. Like this:
class B
{
public:
A<int> value;
};
But now i want to use any kind of template-class in class A. Not only int.
Apparent I can't declare a (member-)variable which contains any kind of a class.
So, I need something like this:
class B
{
public:
A<*> value;
};
Is there any (clean) solution for this problem?
-- Greeting from Germany, Bastian
You cannot have a single class B with "any" member object, because B has to be a well-defined class, and A<T> is a different type for different types T. You can either make B a template itself:
template <typename T>
class B
{
A<T> value;
};
or you can take a look at boost::any, which is type-erasing container for arbitrary types (but making use of it requires a certain amount of extra work). The any class only works for value types, though, it's not completely arbitrary.
The simplest solution would be to make all A variants ineherit from a common interface, even if it's empty :
class IA{}
template <class T>
class A : public IA
{
public:
T value;
};
class B
{
public:
IA* value;
};
Now, the associated costs:
interactions with value are limited to the IA interface;
if you try to cast to get the real type, that mean that you know the real type, so it's of no use and make A type a parameter of B becomes really easier to use.
there are runtime costs associated to runtime inheritance
Advantage :
it's easily understood by other developers
it naturally limit the types possible to some specific ones
it don't use boost (sometimes, you just can't)
So to do better there are other less simple solutions but that are simple enough to be used :
If you can use boost, boost::any, boost::variant and boost::mpl might be base of solutions.
Boost any can be used as a safe replacement to void*. The only problem with this is that you can have ANY type, like if the type was a template parameter of the B class.
Boost variant might be used successfully if you know all the types that A can be.
MPL might be helpful if you just want to set a list of possible types and make sure your members apply only to them. You can do a ton of things with MPL so it really depends on your exact needs.
You've got two choices, I think. The first is to parameterize your class over the type parameters of the instance variables:
template <class T> struct B
{
A<T> value;
};
The other option is to declare value as a void* pointer. (But that's probably not what you want).
yes, it's already been done. boost::any.
I think it helps to understand, that templated classes create an entirely new and seperate class for every type you use with it. For instance, Vector<int> and Vector<float> are as separate as the classes VectorInt and VectorFloat.
For class B, you are basically asking that the value variable either be A<int> or A<float>, which is the same as saying you want value to either be a "A_int" or "A_float". And to accomplish that you... well, use another template!
question about c++
why minimal number of data members in class definition is zero
i think it should be one , i.e pointer to virtual table defined by compiler
thanks a lot
It is often useful to have a class with no data members for use in inheritance hierarchies.
A base class may only have several typedefs that are used in multiple classes. For example, the std::iterator class template just has the standard types defined so that you don't need to define them in each iterator class.
An interface class typically has no data members, only virtual member functions.
A virtual table has nothing to do with the data members of a class.
I’m working on a library that sometimes even uses types that – gasp! – aren’t even defined, much less have data members!
That is, the type is incomplete, such as
struct foobar;
This is used to create an unambiguous name, nothing more.
So what is this useful for? Well, we use it to create distinct tags, using an additional (empty, but fully defined) type:
template <typename TSpec>
struct Tag {};
Now you can create distinct tags like so (yes, we can declare the type inside the template argument list, we do not need to declare it separately):
using ForwardTag = Tag<struct Forward_>;
using RandomAccessibleTag = Tag<struct RandomAccessible_>;
These in turn can be used to disambiguate specialized overloads. Many STL implementations do something similar:
template <typename Iter>
void sort(Iter begin, Iter end, RandomAccessibleTag const&) …
Strictly speaking, the indirect route via a common Tag class template is redundant, but it was a useful trick for the sake of documentation.
All this just to show that a (strict, static) type system can be used in many different ways than just to bundle and encapsulate data.
Well, actually C++ mandates that all classes must occupy some space (You need to be able to generate a pointer to that class). They only need a pointer to a vtable though, if the class is polymorphic. There's no reason for a vtable at all in a monomorphic class.
Another use of a class with no data-members is for processing data from other sources. Everything gets passed into the class at runtime through pointers or references and the class operates on the data but stores none of it.
I hadn't really thought about this until I saw it done in a UML class I took. It has it's uses, but it does usually create coupled classes.
Because classes are not structures. Their purpose, contrary to popular belief, is not to hold data.
For instance, consider a validator base class that defines a virtual method which passes a string to validate, and returns a bool.
An instance of a validator may refuse strings which have capital letters in them. This is a perfect example on when you should use a class, and by the definition of what it does, there's clearly no reason to have any member variables.
question about c++ why minimal number of data members in class definition is zero
It is zero because you have various cases of classes that should have no members:
You can implement traits classes containing only static functions for example. These classes are the equivalent of a namespace that is also recognizable as a type. That means you can instantiate a template on the class and make sure the implementation of that template uses the functions within the class. The size of such a traits class should be zero.
Example:
class SingleThreadedArithmetic
{
static int Increment(int i) { return ++i; }
// other arithmetic operations implemented with no thread safety
}; // no state and no virtual members -> sizeof(SingleThreadedArithmetic) == 0
class MultiThreadedArithmetic
{
static int Increment(int i) { return InterlockedIncrement(i); }
// other arithmetic operations implemented with thread safety in mind
}; // no state and no virtual members -> sizeof(MultiThreadedArithmetic) == 0
template<class ThreadingModel> class SomeClass
{
public:
void SomeFunction()
{
// some operations
ThreadingModel::Increment(i);
// some other operations
}
};
typedef SomeClass<SingleThreadedArithmetic> SomeClassST;
typedef SomeClass<MultithreadedArithmetic> SomeClassMT;
You can define distinct class categories by implementing "tag" classes: classes that hold no interface or data, but are just used to differentiate between separate "logical" types of derived classes. The differentiation can be used in normal OOP code or in templated code.
These "tag" classes have 0 size also. See the iterators tags implementation in your current STL library for an example.
I am sure there are other cases where you can use "zero-sized" classes.