Reputation: 1410
I tried to use templates and structs, but they don't work. I searched a lot, but I can't find the solution.
#include <iostream>
using namespace std;
template<struct S>
int add(S s) {
return s.num + s.num2;
}
int main() {
struct {
int num = 10;
int num2 = 20;
} test;
cout << add(test) << endl;
return 0;
}
With gcc the errors are:
test.cpp:5:17: error: ‘struct S’ is not a valid type for a template non-type parameter
test.cpp: In function ‘int add(S)’:
test.cpp:6:5: error: ‘s’ has incomplete type
test.cpp:5:17: error: forward declaration of ‘struct S’
test.cpp: In function ‘int main()’:
test.cpp:13:19: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]
test.cpp:14:20: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]
test.cpp:17:21: error: no matching function for call to ‘add(main()::<anonymous struct>&)’
test.cpp:17:21: note: candidate is:
test.cpp:6:5: note: template<<declaration error> > int add(S)
test.cpp:6:5: note: template argument deduction/substitution failed:
test.cpp:17:21: note: cannot convert ‘test’ (type ‘main()::<anonymous struct>’) to type ‘S’
Upvotes: 8
Views: 18932
Reputation: 275260
Your problem is that you once saw someone write:
template<class A>
bool foo( A* a ) {
return *a;
}
or something similar, and thought that class
meant that A had to be a class
.
What is actually happening here is that C++ syntax sometimes sucks. Back when templates where first written up, they reused a keyword (class
) in the template argument list to mean "a type", as opposed to the other things you can pass to a template (like an int
).
This is a very confusing bit of syntax. As it happens, this is equivalent to the above:
template<typename A>
bool foo( A* a ) {
return *a;
}
except it makes it much clearer that A can be any type.
However, there is lots of C++ code hanging around from when class
was the proper way to specify "a type" in a template parameter, so C++ continues to allow it.
Upvotes: 1
Reputation: 19757
You can't use the keyword struct
here. Use class
or typename
(you can still instantiate your template with a struct
though).
EDIT: Your other problems are to do with the anonymous struct
in main
. Can't remember the rules off the top of my head (perhaps someone else can explain them), but this is a pretty weird way of doing things anyway, so I just offer a working version: http://ideone.com/VGIogH
Somewhat relevant: Can we have an anonymous struct as template argument?
EDIT AGAIN: What you originally wrote, with the anonymous struct
in main
works (after replacing struct
in the template) with --std=c++11
, but not without (i.e. c++03).
Upvotes: 9
Reputation: 1290
Additionally to replacing struct with typename in the template, my compiler (GCC) says you can't initialize your struct members directly, so you can do it like this:
#include <iostream>
using namespace std;
template<typename S>
int add(S s) {
return s.num + s.num2;
}
int main() {
struct {
int num;
int num2;
} test;
test.num = 10;
test.num2 = 20;
cout << add(test) << endl;
return 0;
}
EDIT: You must let your template know what is your struct:
#include <iostream>
using namespace std;
struct MyStruct {
int num;
int num2;
};
template<typename S>
int add(S s) {
return s.num + s.num2;
}
int main() {
MyStruct test;
test.num = 10;
test.num2 = 20;
cout << add(test) << endl;
return 0;
}
Upvotes: 1
Reputation: 10936
It won't work with anonomous types and you must specify the type in the function call:
#include <iostream>
using namespace std;
template<typename S>
int add(S s) {
return s.num + s.num2;
}
int main() {
struct A {
int num = 10;
int num2 = 20;
} test;
cout << add<A>(test) << endl;
return 0;
}
Upvotes: -2
Reputation: 208323
In C++ a struct
and a class
are basically the same thing, except that the default access specifier is public
in the former and private
in the latter. On the other hand, the syntax for defining a template type argument requires the use of either the class
or typename
keywords (Don't confuse class
here with a class in the OO sense, it can be any type).
template <typename S> // equivalently class S
int add(S s) ...
Upvotes: 6