How can I have multiple typename arguments in a c++ template?
#ifndef _CALL_TEMP_H #define _CALL_TEMP_H #include <string> #include <iostream> template <typename Sig> class Foo; template <typename A, typename B> class Foo { public: void output() { std::cout << a_ << b_ << std::endl; } A a_; B b_; }; template <typename A, typename B, typename C> class Foo { public: void output() { std::cout << a_ << b_ << c_ << std::endl; } A a_; B b_; C c_; }; #endif
Usage:
int main() { Foo<int ,int> doubleint; doubleint.a_ = 1; doubleint.b_ = 2; doubleint.output(); // Foo<int , int , std::string> comp; // comp.a_ = 1; // comp.b_ = 2; // comp.c_ = "haha"; // comp.output(); return 0; }
But it will not compile. How could I make it compile?
Function Templates with Multiple Parameters of different types (in same function) We can use more than one generic type in the template function by using the comma to separate the list.
Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
Just declare a primary template with a variadic template and then specialize for each supported number of template arguments. For example:
#ifndef CALL_TEMP_H #define CALL_TEMP_H #include <iostream> template <typename...> class Foo; template <typename A, typename B> class Foo<A, B> { public: void output() { std::cout << a_ << b_ << '\n'; } A a_; B b_; }; template <typename A, typename B, typename C> class Foo<A, B, C> { public: void output() { std::cout << a_ << b_ << c_ << '\n'; } A a_; B b_; C c_; }; #endif
I you can't use C++11 and you want to retain a similar notation you'll need to simulate a variadic argument list with template default arguments. This will implicitly limit the number of templare arguments but since you are specializing the templates anyway, this limitation doesn't realky matter.
If it is acceptable to use a different notation you can also use something which looks like a function declaration to instantiate and specialize your template:
template <typename> class Foo; template <typename A, typename B> class Foo<void(A, B)> { ... }; template <typename A, typename B, typename C> class Foo<void(A, B, C)> { ... }; ... Foo<void(int, int)> f2; Foo<void(int, int, std::string)> f3;
Whether the change in notation is acceptable depends on your use of the class template. You won't achieve an ideal solution as with variadic templates without C++11, though.
BTW, don't overuse std::endl
: use '\n'
to mean end of line. If you really mean to flush the stream, use std::flush
. Also _CALL_TEMP_H
is a name reserved to the standard C++ library as are all names starting with an underscore followed by a capital character: do not use these names in your own code unless there is explicit permission to use them (e.g. __FILE__
and __LINE__
are reserved but explicit permission to use them is granted).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With