generics JAVA in c++? how to do <X extends T>? - c++

class T : public std::string {
public:
T(char* s) : std::string(s){};
};
class X : public T {
public:
X(char* s) : T(s) {};
~X() {};
};
template <typename T> T doIt(const T arg);
int main(int argc, const char* argv[]) {
X s("initial string");
T s2 = doIt(s);
printf("out %s", s2.c_str());
}
T doIt(T arg) {
arg.append(" appended");
return arg;
};
What is the problem with my code.. the output is bellow...
1>Linking...
1>TemplateStuding1.obj : error LNK2001: unresolved external symbol "class X __cdecl doIt(class X)" (??$doIt#VXClass####YA?AVXClass##V0##Z)
1>D:\Programming\cpp\cpp-how-to-program\CppHowToProgram\Release\Test.exe : fatal error LNK1120: 1 unresolved externals

Once you get past the problem with the missing template <class T> on your definition of doIt (that others have already mentioned), you'll still want an answer to your question:
Is it possible to make a template argument <X extends T> like in Java?
The answer to this question is no. C++ does not have constrained generics like Java does. There was a proposal on the table to add something like this (but much different) called "concepts" in C++0x, but it was just too complicated and has been dropped.
In brief, there are 3 ways to do generics that are relevant:
Duck typing (what Ruby has). This is what C++ has now. If an class responds to all of the same methods as class T then it will fit the bill, even if it's not inherited from class T. In addition, if you try to pass class Z which is missing some methods that class T has, you'll never find out if the template doesn't try to call them. If the template does try to call them, then a compiler error will appear at the place where the template tries to call the missing method. (You'll find out which template instantiation caused the problem from a stack trace that the compiler will spit out explaining what templates it was trying to instantiate when it encountered the error.) You do get a compiler error in C++ (unlike Ruby, where it's a runtime error), but it's a complicated error message.
Structural typing (what Scala has). Concepts in C++ were intended to move in this direction. If an class responds to all of the same methods as class T then it will fit the bill, even if it's not inherited from class T. If that class doesn't respond to all of the same methods, it's an error, even if the template function doesn't try to call the missing method. Template errors are reported at the site of instantiation. (C++'s version of this would be more complicated because you can do declare operators on an object as free functions, but the basic idea is the same.)
Constrained generics (for lack of a better term -- what Java has). Any class passed to the template must be a subtype of class T. Having the same methods won't cut it unless there's real inheritance. Members of the C++ standardization commitee don't like this -- they prefer #2 over #1 (if they can work out all of the technical issues) and #1 over #3 -- so it will probably never appear in C++.
Would someone else please post an answer untangling this guy's use of class T in this example. He's using it in 2 different ways, and I'm not sure whether his use of T in template <class T> (as opposed to some other letter) was meant to specify a constraint on the types that could be passed. This may be a significant confusion. On the other hand, using T in both places may just be a careless error. I really can't tell.

Here is the problem:
template <typename T> T doIt(const T arg); // <---- declared but not defined
int main(int argc, const char* argv[]) {
//...
T s2 = doIt(s); // <------ it is calling above method (which is visible)
}
T doIt(T arg) { // <------ T is `class T`, not `template`, so different method
arg.append(" appended");
return arg;
};
Here when you define T doIt(T) after main(), you expect that you are defining the body of the above template method. Which is not true. You don't get compiler error because, coincidentally you have class T; which will pass the definition of T doIt(T).
If you intend to use template doIt then your definition should be as,
template<typename T>
T doIt(T arg) { // <------ T is now `template`; thus same method
arg.append(" appended");
return arg;
};
[Also note that, you get linker error because you din't have any real definition of template doIt and whatever definition you had below main() was not visible.]

Your compiler is complaining that you declared but never implemented doIt. All it is right now is a signature, and yet you're calling it like it's actually defined.
On a side note, what on earth does this error have to do with java? Or generics even?

Related

C++ Error C2228 (left of '.val' must have class/struct/union) in unusual circumstances

In C++, I am trying to implement my own any class using C++. However, before I was able to test it (so if my implementation is bad, feel free to correct me), I got the error: error C2228: left of '.val' must have class/struct/union twice from using the value() function twice, which seems weird when it works everywhere else. The only thing I could think of would be that decltype infront of a function is causing an error, but it shouldn't:
Edit: I have updated the way of changing the variable for the template<class T> any(T V){...} constructor
class any{
protected:
template<class T> struct variable{
public:
T val;
variable(){}
variable(T t) : val(t){}
};
variable<int> v;
public:
any(){
v.val = 0;
}
template<class T> any(T V){
variable<T> nV(V);
v = nV;
}
~any(){
delete &v;
}
decltype(v.val) value(){ // Error still here
return v.val;
}
template<class T> static any create(T V){
return any(V);
}
};
You seem to have a big misunderstanding about this line:
T = NewT;
In C++, the T is a template parameter and therefore it is static during compilation. You can not "set" it as it is not a variable. Unlike some dynamic languages (Python, ...) in C++ types are not objects and can not be modified during runtime. You can instantiate the template with different types (different Ts), but each is like a separate class (called a template class instantiation or class template instantiation, both are equivalent) and it is independent of the other instances.
Since the rest of your design is based on the above false assumption, you run into a lot of problems. The reason that the above line is not showing up as the first error is that it is not even instantiated before other part of the code are compiled (technically: different stages of compilation). That said, you need to understand why the above is impossible in C++ and the rest will follow. You may want to look into other implementations like Boost.Any to get some ideas on how it could be done. (Warning: It's more complicated than your approach)

Nested class as a template parameter of parent class in C++

I want to implement an algorithm as a class deriving from a pure virtual class representing the kind of problem the particular algorithm solves.
The general interface would look like this:
template<typename A, typename B>
class ISolutionToProblem
{
public:
virtual void Init(const A & input, const B & param) = 0;
virtual const B & ComputeSolution() = 0;
virtual ~ISolutionToProblem() {}
};
And the implementation would be for example:
template<typename T>
class MyAlgorithm:
public ISolutionToProblem<typename MyAlgorithm<T>::WorkData, T>
{
public:
struct WorkData { /* Stuff using T... */ };
virtual void Init(const WorkData & input, const T & param);
virtual const T & ComputeSolution();
virtual ~MyAlgorithm();
};
(to be more specific, the problem is actually path finding, but I don't think it is relevant)
My problem is the inheritance part: I am using a nested struct as a template parameter, and no matter how nicely I try to talk to the compiler, it keeps refusing to compile my code.
I could go lazy and just put the inner structure outside of the class, but if possible I'd prefer it to stay neatly placed in the class.
So is what I am trying to do actually possible (in C++98)?
If so, how should I write it ? (bonus points if you get me to understand why the syntax doesn't accept the form above)
Otherwise, what am I doing wrong? (is my design flawed to begin with?)
Here is how the compiler error looks like.
g++ (4.8):
error: no type named ‘WorkData’ in ‘class MyAlgorithm<int>’
clang (3.1):
error: no type named 'WorkData' in 'MyAlgorithm<T>'
VS2012:
error C2146: syntax error : missing ',' before identifier 'WorkData'
see reference to class template instantiation 'MyAlgorithm<T>' being compiled
error C2065: 'WorkData' : undeclared identifier
error C2955: 'ISolutionToProblem' :
use of class template requires template argument list
see declaration of 'ISolutionToProblem'
I think your problem is the the compiler doesn't know what the inner class looks like until it has defined the outer class and the outer class is defined with the inner class as a template parameter. I'm not 100% sure this can't be made to work. The CRTP is an example similar to this that is known to work.
Templates can be used to create inheritance hierarchies, but should not be use the in the definition of a hierarchy. If that sounds confusing, it's because it is. Inheritance and template classes don't mix well. Notice that even though CRTP uses inheritance and templates it does not use virtual functions.

Generic class variable of a certain type

In C# I can define this:
public interface BaseObject
{
int GetValue();
}
public class Test<T> where T : BaseClass
{
T BaseObject;
}
which means I know that I can alwaysa call BaseObject.GetValue() / BaseObject->GetValue(); because I know that the baseobject has this method.
Is there a similiar way to do this in C++? So that I can define an interface that multiple classes can inherit and a class that can take advantage of this.
Templates, which are even more powerful than C# generics (not to say they are necessarily better, just different).
template<class T>
class foo
{
public:
int whatever()
{
return obj.GetValue();
}
private:
T obj;
};
A separate class is created for each template argument you use. If you provide a template type which would result in an error you will know at compile time.
You're asking about C++ concepts, a way to specify requirements for template parameters. They were proposed during the work on C++11, but proved complicated enough that they weren't done in time. But they've just been delayed, not forgotten.
In the meantime, duck typing remains very powerful, and it will catch when you pass a template parameter that doesn't have the required interface. It just won't report the problem as neatly.
As a workaround, a simple way to check the constraint you showed takes advantage of the fact that pointer conversions are implicit only when upcasting:
public class Test<T> where T : BaseClass
{
static T* enforcement_helper = 0;
static BaseClass* enforce_inheritance_constraint = enforcement_helper;
};
Depending on how new your compiler is, you may need to put those lines inside a special member function (destructor is good, because it's almost always processed).
But you should only check constraints in order to improve error messages (by causing the failure in a clearly commented section of code). C++ templates are duck typed, and they will work with any template parameters that provide the required operations. No formal "interface" is required.

C++ Template Basics - Function Accept Sub Class or Super

Say you have a sub class B which inherits from super class A. You want a function that can accept either A or B.
template <typename T>
void someFunc(T* pObj, bool someOtherArg)
{
pObj->AnInheritMethod();
if (pObj->IsASub())
{
pObj->ANonInhertMethod();
}
}
When I compile this (Visual Studio 6) I get:
error C2065: 'pObj' : undeclared identifier
Am I way off base here?
You don't need a function template for this; the following will do just fine:
void someFunc(A* pObj)
{
pObj->AnInheritMethod();
if (B* pObjAsB = dynamic_cast<B*>(pObj))
{
pObjAsB->ANonInheritMethod();
}
}
Or, if you prefer to use your IsASub() member function instead of dynamic_cast:
void someFunc(A* pObj)
{
pObj->AnInheritMethod();
if (pObj->IsASub())
{
B* pObjAsB = static_cast<B*>(pObj);
pObjAsB->ANonInheritMethod();
}
}
Aside from the missing return type, I don't see anything obviously wrong with the code in your example; I don't have Visual C++ 6 installed to check.
You don't need templates for that, that is a free behaviour courtesy of polymorphism.
Edit: also if you write something like:
if (pObj->IsASub())
then there's maybe something wrong in your design. The method is supposed to work for any type in the derivation chain.
You're asking a question that is completely unrelated to the code and error that you included.
In order to have a function take an A or a class derived from A, all it needs to do is take a pointer or reference to A, e.g.
someFunc(A* pObj, bool someOtherArg);
or
someFunc(A& obj, bool someOtherArg);
It will work by virtue of inheritance. That's kind of the whole point of deriving classes from each other. The way you have written it with templates, it will work with any class that defines the three methods you use, whether or not it derives from A.
Now the error you posted is unrelated to this question but is bizarre. There's nothing wrong with the code you posted, but Visual Studio 6 is an ancient compiler; it's twelve years old and does not fully support modern ISO standard C++. This error may be an artifact of a sub-standard templating implementation in the compiler.

Any way to determine if class implements operator()

I'm trying to find is there's a way to check if a class is a functional because i want to write a template which uses it?
Is there an easy way to do this? Or do I just wrap things in a try/catch? Or perhaps the compiler won't even let me do it?
If you have a function template written like:
template <typename T>
void f(T x)
{
x();
}
you will be unable to instantiate it with any type that is not callable as a function taking no arguments (e.g., a class type that overloads operator() taking no arguments is callable as a function that takes no arguments). You would get a compilation error if you tried to do so.
This is the simplest way to require the type with which a template is instantiated to have certain properties: just rely on the type having those properties when you write the template, and if the type doesn't have one of the required properties, it will be impossible to instantiate the template with that type.
There are quite a few ways a parameter type can be applicable to the call syntax
Type is a pointer or reference to a function type, or
Type is a class-type which has a conversion function to one of the types in 1., or has an applicable operator().
The current C++ cannot check for 2., so you are left without checking, like the other answers explain.
This would fall under doing it and getting a compiling error. When the code is compiled the template function or template classes are are expanded for the types used as if there were duplicate copies of that template code, one for each type.
So you can basically do whatever and as long as all the types used for your templates support it you have no problem. If they don't support it you have a compiling error and you can't run your code without fixing it.
template <typename T>
void DoIt(T a)
{
a.helloworld();//This will compile fine
return a();//This will cause a compiling error if T is B
}
class A
{
public:
void a.helloworld(){}
void operator()(){}
};
class B
{
public:
void a.helloworld(){}
};
int main(int argc, char**argv)
{
A a;
B b;
DoIt(a);
DoIt(b);//Compiling error
return 0;
}
If you actually need a test to see if type T implements an operator() of some given signature then you could use the same SFINAE trick used to identify the existence of any other class member that is discussed here: C++ "if then else" template substitution