简体   繁体   中英

C++ struct template

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’

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 (ie c++03).

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) ...

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;
}

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM