So, I'm learning C++, and I've run into something which I know how to do in Java, but not in C++ :).
I have a template for a container object, which is defined as such:
template <class T>
class Container {
vector<T> contained;
public:
void add(T givenObject) {
this->contained.push_back(givenObject);
}
T get(string givenIdentifier) throw (exception) {
for (int i = 0; i < this->contained.size(); i++) {
if (this->contained[i].getIdentifier() == givenIdentifier) {
return this->contained[i];
}
}
throw new exception("An error has occured which has caused the object you requested to not be found. Please report this bug.");
}
bool empty() {
return this->contained.empty();
}
bool identifierExists(string givenIdentifier) {
for (int i = 0; i < this->contained.size(); i++) {
if (this->contained[i].getIdentifier() == givenIdentifier) {
return true;
}
}
return false;
}
};
This actually works very well, with one small issue. It comes down to two lines: the first is the template definition and the second is
this->contained[i].getIdentifer()
In Java, when declaring a Generic (template) one can define a superclass/interface which all members of T must extend in order to not create an error. However, I'm not sure of a way to do this in C++, and my concern is that coupling the implementation here to a getIdentifier method which might not be defined is bad design.
Now, it's not a huge deal if that's the case, this is just a little challenge project to help me learn the language, but I like to try to do things right. Is there a way to do what I'm thinking? I know you can do it with primitives, for instance:
template <int T>
is valid, but when I try to use a user defined class, I get a compiler error. Any suggestions?
It's not possible for you to put artificial limitations on template type parameters. If the type given doesn't support the way you use it, you'll receive a compiler error. A feature called 'concepts,' which would essentially allow this, was going to be added to the next C++ standard, but it was delayed to the next-next standard due to time constraints. If T doesn't have a visible getIdentifier() function, the instantiation won't compile.
Template parameters need to be deduced at compile time. template<int T> is valid because the first template parameter is an integer; you can instantiate it with any constant integer. If you attempted to use it with a non-const integer variable, it wouldn't compile. An instance of a class isn't a compile time constant, so it can't be used.
You've gotten a couple of other answers, both quite good (especially #dauphic's, IMO). I'd just add that the code you've given really looks an awful lot like quite an inefficient imitation of an std::map. Under most circumstances, std::map will probably work better. If you look up its interface, it'll also show you a way to decouple your container from having to specify getIdentifier() directly -- instead of directly using something like getIdentifier(), it uses a comparison functor that defaults to std::less<T>, which will (in turn) use T::operator< -- but you can also specify an entirely different comparison functor if you prefer.
I should also point out that while others have pointed out that you'll get a compile error if you use getIdentifier (or whatever) and attempt to instantiate over a class that doesn't supply it. I feel obliged to warn you, however, that the error message you get may be long, convoluted, and quite difficult to decipher. This is especially likely if there's some other type that does have a getIdentifier member available. In this case the error message you get say something like "Unable to to convert from type A to type B", where type A is whatever type you used to instantiate the container, and type B is whatever (often entirely unrelated) type that happens to have a getIdentifier member. What's happening is that the compiler sees that you've used getIdentifier, and sees that type B has that, so it tries to convert your type A object to a type B object, and finds that it can't, so that's what it tells you about in the error message.
P.S. Yes, I know this is really more of a comment than an answer. I apologize for that, but it won't really fit in a comment.
You don't have to do anything. If contained[i] doesn't have a getIdentifer() function, you will get a compile-time error (just as you would using an interface contrainst in Java, and just as you would outside of using templates).
To elaborate: If you were to write,
int x = 10;
long id = x.getIdentifer();
That would be considered a "bad design". It would just be a mistake, which the compiler will catch. That is exactly what will happen in you're example.
C++ draws a pretty stark line between compile-time polymorphism (ie Templates) and run-time polymporphism (ie inheritance). So what you want to do is not supported by the language.
One typical practice to do what you are doing is to provide, in addition to T, a type that can get an identifier of a given T. This decouples the two behaviors into two types and you can specify (in English) the interface that must be implemented.
template <class T, class StringIdForT>
class Container
{
...
bool identifierExists(string givenIdentifier)
{
StringIdForT idGetter;
for (int i = 0; i < this->contained.size(); i++)
{
if (idGetter.getIdentifier(this->contained[i]) == givenIdentifier)
{
return true;
}
}
return false;
}
};
You have a similar problem, StringIdForT must still define a specified method
Related
I am trying to implement a C++ class which will wrap a value (among other things). This value may be one of a number of types (string, memory buffer, number, vector).
The easy way to implement this would be to do something like this
class A {
Type type;
// Only one of these will be valid data; which one will be indicated by `type` (an enum)
std::wstring wData{};
long dwData{};
MemoryBuffer lpData{};
std::vector<std::wstring> vData{};
};
This feels inelegant and like it wastes memory.
I also tried implementing this as a union, but it came with significant development overhead (defining custom destructors/move constructors/copy constructors), and even with all of those, there were still some errors I encountered.
I've also considered making A a base class and making a derived class for each possible value it can hold. This also feels like it isn't a great way to solve the problem.
My last approach would be to make each member an std::optional, but this still adds some overhead.
Which approach would be the best? Or is there another design that works better than any of these?
Use std::variant. It is typesafe, tested and exactly the right thing for a finite number of possible types.
It also gets rid of the type enum.
class A {
std::variant<std::wstring, long, MemoryBuffer, std::vector<std::wstring>> m_data{}; // default initializes the wstring.
public
template<class T>
void set_data(T&& data) {
m_data = std::forward<T>(data);
}
int get_index() { // returns index of type.
m_data.index();
}
long& get_ldata() {
return std::get<long>(m_data); // throws if long is not the active type
}
// and the others, or
template<class T>
T& get_data() { // by type
return std::get<T>(m_data);
}
template<int N>
auto get_data() { // by index
return std::get<N>(m_data);
}
};
// using:
A a;
a.index() == 0; // true
a.set_data(42);
a.index() == 1; // true
auto l = a.get<long>(); // l is now of type long, has value 42
a.get<long>() = 1;
l = a.get<1>();
PS: This example does not even include the coolest (in my opinion) feature of std::variant: std::visit I am not sure what you want to do with your class, so I cannot create a meaningful example. If you let me know, I will think about it.
You basically want QVariant without the rest of Qt, then :)?
As others have mentioned, you could use std::variant and put using MyVariant = std::variant<t1, t2, ...> in some common header, and then use it everywhere it's called for. This isn't as inelegant as you may think - the specific types to be passed around are only provided in one place. It is the only way to do it without building a metatype machinery that can encapsulate operations on any type of an object.
That's where boost::any comes in: it does precisely that. It wraps concepts, and thus supports any object that implements these concepts. What concepts are required depends on you, but in general you'd want to choose enough of them to make the type usable and useful, yet not too many so as to exclude some types prematurely. It's probably the way to go, you'd have: using MyVariant = any<construct, _a>; then (where construct is a contract list, an example of which is as an example in the documentation, and _a is a type placeholder from boost::type_erasure.
The fundamental difference between std::variant and boost::any is that variant is parametrized on concrete types, whereas any is parametrized on contracts that the types are bound to. Then, any will happily store an arbitrary type that fulfills all of those contracts. The "central location" where you define an alias for the variant type will constantly grow with variant, as you need to encapsulate more type. With any, the central location will be mostly static, and would change rarely, since changing the contract requirements is likely to require fixes/adaptations to the carried types as well as points of use.
I am trying to get my head around applying template programming (and at some future point, template metaprogramming) to real-world scenarios. One problem I am finding is that C++ Templates and Polymorphism don't always play together the way I want.
My question is if the way I'm trying to apply template programming is improper (and I should use plain old OOP) or if I'm still stuck in the OOP mindset.
In this particular case, I am trying to solve a problem using the strategy-pattern. I keep running into the problem where I end up wanting something to behave polymorphically which templates don't seem to support.
OOP Code using composition:
class Interpolator {
public:
Interpolator(ICacheStrategy* const c, IDataSource* const d);
Value GetValue(const double);
}
void main(...) {
Interpolator* i;
if (param == 1)
i = new Interpolator(new InMemoryStrategy(...), new TextFileDataSource(...));
else if (param == 2)
i = new Interpolator(new InMemoryStrategy(...), new OdbcDataSource(...));
else if (param == 3)
i = new Interpolator(new NoCachingStrategy(...), new RestDataSource(...));
while (run) {
double input = WaitForRequest();
SendRequest(i->GetValue(input));
}
}
Potential Template Version:
class Interpolator<class TCacheStrategy, class TDataSource> {
public:
Interpolator();
Value GetValue(const double); // may not be the best way but
void ConfigCache(const& ConfigObject); // just to illustrate Cache/DS
void ConfigDataSource(const& ConfigObject); // need to configured
}
//Possible way of doing main?
void main(...) {
if(param == 1)
DoIt(Interpolator<InMemoryStrategy, TextFileDataSource>(), c, d);
else if(param == 2)
DoIt(Interpolator<InMemoryStrategy, OdbcDataSource>(), c, d)
else if(param == 3)
DoIt(Interpolator<NoCachingStrategy, RestDataSource>(), c, d)
}
template<class T>
void DoIt(const T& t, ConfigObject c, ConfigObject d) {
t.ConfigCache(c);
t.ConfigDataSource(c);
while(run) {
double input = WaitForRequest();
SendRequest(t.GetValue(input));
}
}
When I try to convert the OOP implementation to a template-based implementation, the Interpolator code can be translated without a lot of pain. Basically, replace the "interfaces" with Template type parameters, and add a mechanism to either pass in an instance of Strategy/DataSource or configuration parameters.
But when I get down to the "main", it's not clear to me how that should be written to take advantage of templates in the style of template meta programming. I often want to use polymorphism, but it doesn't seem to play well with templates (at times, it feels like I need Java's type-erasure generics... ugh).
When I often find I want to do is have something like TemplateType<?, ?> x = new TemplateType<X, Y>() where x doesn't care what X, Y is.
In fact, this is often my problem when using templates.
Do I need to apply one more level of
templates?
Am I trying to use my shiny new power template wrench to
install a OOP nail into a PCI slot?
Or am I just thinking of this all
wrong when it comes to template
programming?
[Edit] A few folks have pointed out this is not actually template metaprogramming so I've reworded the question slightly. Perhaps that's part of the problem--I have yet grok what TMP really is.
Templates provide static polymorphism: you specify a template parameter at compile time implementing the strategy. They don't provide dynamic polymorphism, where you supply an object at runtime with virtual member functions that implement the strategy.
Your example template code will create three different classes, each of which contains all the Interpolator code, compiled using different template parameters and possibly inlining code from them. That probably isn't what you want from the POV of code size, although there's nothing categorically wrong with it. Supposing that you were optimising to avoid function call overhead, then it might be an improvement on dynamic polymorphism. More likely it's overkill. If you want to use the strategy pattern dynamically, then you don't need templates, just make virtual calls where relevant.
You can't have a variable of type MyTemplate<?> (except appearing in another template before it's instantiated). MyTemplate<X> and MyTemplate<Y> are completely unrelated classes (even if X and Y are related), which perhaps just so happen to have similar functions if they're instantiated from the same template (which they needn't be - one might be a specialisation). Even if they are, if the template parameter is involved in the signatures of any of the member functions, then those functions aren't the same, they just have the same names. So from the POV of dynamic polymorphism, instances of the same template are in the same position as any two classes - they can only play if you give them a common base class with some virtual member functions.
So, you could define a common base class:
class InterpolatorInterface {
public:
virtual Value GetValue(const double) = 0;
virtual void ConfigCache(const& ConfigObject) = 0;
virtual void ConfigDataSource(const& ConfigObject) = 0;
virtual ~InterpolatorInterface() {}
};
Then:
template <typename TCacheStrategy, typename TDataSource>
class Interpolator: public InterpolatorInterface {
...
};
Now you're using templates to create your different kinds of Interpolator according to what's known at compile time (so calls from the interpolator to the strategies are non-virtual), and you're using dynamic polymorphism to treat them the same even though you don't know until runtime which one you want (so calls from the client to the interpolator are virtual). You just have to remember that the two are pretty much completely independent techniques, and the decisions where to use each are pretty much unrelated.
Btw, this isn't template meta-programming, it's just using templates.
Edit. As for what TMP is, here's the canonical introductory example:
#include <iostream>
template<int N>
struct Factorial {
static const int value = N*Factorial<N-1>::value;
};
template<>
struct Factorial<0> {
static const int value = 1;
};
int main() {
std::cout << "12! = " << Factorial<12>::value << "\n";
}
Observe that 12! has been calculated by the compiler, and is a compile-time constant. This is exciting because it turns out that the C++ template system is a Turing-complete programming language, which the C preprocessor is not. Subject to resource limits, you can do arbitrary computations at compile time, avoiding runtime overhead in situations where you know the inputs at compile time. Templates can manipulate their template parameters like a functional language, and template parameters can be integers or types. Or functions, although those can't be "called" at compile time. Or other templates, although those can't be "returned" as static members of a struct.
I find templates and polymorphism work well toegther. In your example, if the client code doesn't care what template parameters Interpolator is using then introduce an abstract base class which the template sub-classes. E.g.:
class Interpolator
{
public:
virtual Value GetValue (const double) = 0;
};
template<class TCacheStrategy, class TDataSource>
class InterpolatorImpl : public Interpolator
{
public:
InterpolatorImpl ();
Value GetValue(const double);
};
void main()
{
int param = 1;
Interpolator* interpolator = 0;
if (param==1)
interpolator = new InterpolatorImpl<InMemoryStrategy,TextFileDataSource> ();
else if (param==2)
interpolator = new InterpolatorImpl<InMemoryStrategy,OdbcDataSource> ();
else if (param==3)
interpolator = new InterpolatorImpl<NoCachingStrategy,RestDataSource> ();
while (true)
{
double input = WaitForRequest();
SendRequest( interpolator->GetValue (input));
}
}
I use this idiom quite a lot. It quite nicely hides the templatey stuff from client code.
Note, i'm not sure this use of templates really classes as "meta-programming" though. I usually reserve that grandiose term for the use of more sophisticated compile-time template tricks, esp the use of conditionals, recursive defintions etc to effectively compute stuff at compile time.
Templates are sometimes called static (or compile-time) polymorphism, so yes, they can sometimes be used instead of OOP (dynamic) polymorphism. Of course, it requires the types to be determined at compile-time, rather than runtime, so it can't completely replace dynamic polymorphism.
When I often find I want to do is have something like TemplateType x = new TemplateType() where x doesn't care what X,Y is.
Yeah, that's not possible. You have to do something similar to what you have with the DoIt() function. Often, I think that ends up a cleaner solution anyway (you end up with smaller functions that do just one thing each -- usually a good thing). But if the types are only determined at runtime (as with i in the OOP version of your main function), then templates won't work.
But In this case, I think your template version solves the problem well, and is a nice solution in its own right. (Although as onebyone mentions, it does mean code gets instantiated for all three templates, which might in some cases be a problem)
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.
Once I was asked a question during the interview.
Hence I have a function void f(std::string), and I call a function as this f("int"). So that my function must create a local int x in its body. Is there a way to get the type from const char*. I know that boost::mpl::vector does solve this kind of problem. Can anyone tell me the technique?
If user-defined types are supposed to be supported, then it's not possible without an explicit mapping provided. But for just built-in types, it can be done. You could implement a parser for type definitions and combine it with function templates, constructing the type iteratively. Something like this:
template <class T>
void parseType(std::string type)
{
std::string spec = extractOneSpecifierFrom(type);
if (spec == "[]") {
parseType<T[]>(type);
} else if (spec == "*") {
parseType<T*>(type);
} else if (spec == "const") {
parseType<const T>(type);
} // ... etc.
}
My impression of this question is:
Creating a local int is done during the compile phase.
The argument s to f(std::string s) is runtime data.
So unless you are inspecting the string during runtime and selecting a block, or a predefined template, with an int, like
if ( s == "int" ){
// declare int
int i;
}
there is no reasonable way to do this.
To have object code with every possible data type available during compilation seems to me to go against the spirit of the question.
Now, with languages that has proper reflection the solution is mostly trivial. Object intObject = Class.forName(s).newInstance();
I recently thought about this too. I came up with a class member that is casted at the start of each method based on some string and if/else block.
void* data;
string cast; //set cast with some method, could also be enum.
//make methods and/or overloads with cast blocks
I was wondering that when I create an instance of a class template with specifying the template type parameter.
1) why the non-called function do not get instatiated ? .
2) dont they get compiled until I try to use it ?
3) what is the logic behind this behavior ?
Example
template <class T>
class cat{
public:
T a;
void show(){
cout << a[0];
}
void hello(){
cout << "hello() get called \n";
}
};
int main(){
cat<int> ob1; // I know that show() did not get instatiated, otherwise I will get an error since a is an int
ob1.hello();
}
Templates aren't code - they're a pattern used to make the actual code. The template isn't complete until you supply the parameters so the code can't be made ahead of time. If you don't call a function with a particular set of template parameters, the code never gets generated.
If they instantiated the entire class, then you might get invalid code.
You don't always want that.
Why? Because in C++, it's difficult (and in some cases, outright impossible, as far as I know) to say, "only compile this code if X, Y, and Z are true".
For example, how would you say, "only my copy constructor if the embedded object can be copied"? As far as I know, you can't.
So they just made them not compile unless you actually call them.
To embellish a little more: this is typically called duck typing, and the bottom line is that it allows you to write "class patterns" of which some member functions may apply when instantiated with one template type, other members may apply when instantiated with a second template type, and by only requiring the ones you actually call to compile, you get to write a lot less code for operations that wind up being common ones.
By not requiring all member functions to be compiled you get all the niceties of static type checking on the functions that actually are compiled.
For example, imagine you had:
template <typename E>
class myContainer {
// Imagine that constructors, setup functions, etc. were here
void sort(); // this function might make sense only if E has an operator< defined
E max(); // compute the max element, again only makes sense with a operator<
E getElement(int i); // return the ith element
E transmogrify(); // perhaps this operation only makes sense on vectors
};
Then you have
// sort() and getElement() makes total sense on this, but not transmogrify()
myContainer<int> mci;
// sort and max might not be needed, but getElement() and transmogrify() might
myContainer<vector<double>> mcvd;
No code is generated for cat<int>::show() because you never call it. If you did call it you would get a compilation error. Template functions which are never called do not exist.
Templates are little more than test substitution mechanisms. This makes them very powerful. You, as the programmer, may want to create a cat<int> knowing that you will never call show() or call anything else that would be invalid. The compiler lets you know if you did, so it works out nicely.
So if your question is "why does it work this way", I would ask you "why not"? It's a design choice. This choice allows me to use a template type safely and still benefit from other parts of the code. What's the harm? You also generate less code, which is a good thing, right?