I have a templated class and I want to use a create a templated function inside that class. I can't seem to figure out now to do it.
I boiled it down to a simple program:
#include <iostream>
template<typename TInputType = short,
typename TInternalType = float>
class MyClass
{
public:
void Print();
template<typename TAnotherType> void DoSomething(TAnotherType t);
};
template<typename TInputType, typename TInternalType>
void MyClass<TInputType,TInternalType>::Print()
{
printf("whats up\n");
}
template<typename TInputType, typename TInternalType, typename TAnotherType>
void MyClass<TInputType,TInternalType>::DoSomething(TAnotherType t)
{
std::cout << "whats up:" << t << std::endl;
}
int main() {
MyClass<> tst;
tst.Print();
tst.DoSomething<int>(10);
std::cout << "!!!Hello World!!!" << std::endl;
return 0;
}
I get error: invalid use of incomplete type OR error: too many template parameters in template redeclaration
Ok so... Ive been experimenting and I figured it out.
You need two template calls
...
template<typename TInputType, typename TInternalType>
template<typename TAnotherType>
void MyClass<TInputType,TInternalType>::DoSomething(TAnotherType t)
{
std::cout << "whats up:" << t << std::endl;
}
...
Related
I tried to implement template function specialization. You can run my tiny code in this fiddle. You can also see it below
#include <iostream>
#include <vector>
#include <list>
template <typename T>
struct is_vector {
static const bool value = false;
};
template <typename T>
struct is_vector<std::vector<T>> {
static const bool value = true;
using type = std::vector<T>;
};
template <typename T>
struct is_list {
static const bool value = false;
};
template <typename T>
struct is_list<std::list<T>> {
static const bool value = true;
using type = std::list<T>;
};
template<typename T, class = typename std::enable_if<is_list<T>::value>::type>
void foo(T t) {
std::cout << "is list" << std::endl;
}
/*
template<typename T, class = typename std::enable_if<is_vector<T>::value>::type>
void foo(T t) {
std::cout << "is vector" << std::endl;
}
*/
//The above code will cause an error, if we uncomment it
int main()
{
foo(std::list<int>{});
return 0;
}
In this code, I have several lines commented:
template<typename T, class = typename std::enable_if<is_vector<T>::value>::type>
void foo(T t) {
std::cout << "is vector" << std::endl;
}
If I uncomment it, I get "redifinition" error. I'm not sure how to fix it.
If I uncomment it, I get "redifinition" error. I'm not sure how to fix it.
The reason is quite simple: default values for template type arguments are not a part of a function signature. It means that you have the same template defined two times.
You might move SFINAE part in to the function return type, as it is suggested by other answers, or change the code to:
template<typename T, std::enable_if_t<is_list<T>::value, int> = 0>
void foo(T t) {
std::cout << "is list" << std::endl;
}
template<typename T, std::enable_if_t<is_vector<T>::value, int> = 1>
void foo(T t) {
std::cout << "is vector" << std::endl;
}
You can do this instead.
template<typename T>
typename std::enable_if<is_list<T>::value>::type foo(T t) {
std::cout << "is list" << std::endl;
}
template<typename T>
typename std::enable_if<is_vector<T>::value>::type foo(T t) {
std::cout << "is vector" << std::endl;
}
Not sure if this is what you are after, but you could just check if either list or vector is a matching type:
template<typename T, class = typename std::enable_if<is_list<T>::value || is_vector<T>::value>::type>
void foo(T t) {
std::cout << "is list" << std::endl;
}
Updated fiddle: https://godbolt.org/g/oD3o9q
Update (for C++14):
template<typename T, class = std::enable_if_t<is_list<T>::value || is_vector<T>::value>>
void foo(T t) {
std::cout << "is list" << std::endl;
}
When playing around with good ol' c++ I started wondering whether it is possible to overload a template function based on an enclosing template. At the first layer this looks achievable, however, how can this be done recursively? So that the below pseudo-c++ code
#include <iostream>
#include <vector>
#include <map>
template <typename T> void magic(){
std::cout << "Called magic<T>" << std::endl;
}
template <typename std::vector<T> > void magic(){
std::cout << "Called magic<std::vector<T> >" << std::endl;
magic<T>();
}
template <typename std::map<T,U> > void magic(){
std::cout << "Called magic<std::map<T,U> >" << std::endl;
magic<T>();
magic<U>();
}
int main() {
magic<std::vector<std::map<std::string,std::vector<int> > > >();
}
yields something like:
Called magic<std::vector<T> >
Called magic<std::map<T,U> >
Called magic<T>
Called magic<std::vector<T> >
Called magic<T>
In principle this does not look like it should be impossible because all the type info is available at compile time. The compiler could easily create all required functions since the recursion is bound to stop. And thus the question: Is this possible? If so, how?
Simple specialization should do the trick, but bear in mind that you cannot specialize function templates partially, so you'll need an intermediate class template:
template <typename> void magic();
template <typename T>
struct Impl
{
static void f() { std::cout << "Primary template\n"; }
};
template <typename T, typename A>
struct Impl<std::vector<T, A>>
{
static void f() { std::cout << "A vector\n"; magic<T>(); }
};
template <typename K, typename T, typename P, typename A>
struct Impl<std::map<K, T, P, A>>
{
static void f() { std::cout << "A map\n"; magic<K>(); magic<T>(); }
};
template <typename T> void magic() { Impl<T>::f(); }
You need partial template specialization, that is a template specialization which itself is a template again.
That is not possible with function templates but it is with classes. So the workaround is to create a class template (here called Magic) with the specializations. Within that class, a simple (non-template) function is called.
Then, a function magic forwards to that class in order to hide that "hack":
Live demo of this code snippet
#include <iostream>
#include <vector>
#include <map>
// Forward declaration of the magic function:
template <typename> void magic();
// General case:
template <typename T>
struct Magic {
static void m(){
std::cout << "Called magic<T>" << std::endl;
}
};
// Vector case:
template <typename T>
struct Magic<std::vector<T> > {
static void m(){
std::cout << "Called magic<std::vector<T> >" << std::endl;
magic<T>();
}
};
// Map case:
template <typename T, typename U>
struct Magic<std::map<T,U> > {
static void m(){
std::cout << "Called magic<std::map<T> >" << std::endl;
magic<T>();
magic<U>();
}
};
// Implementation of the magic function:
template <typename T>
void magic() {
std::cout << "Forwarding..." << std::endl;
Magic<T>::m();
}
int main() {
magic<std::vector<std::map<std::string,std::vector<int> > > >();
}
I want to unpack the parameter pack in func (see line A), but it doesnt work. How can I unpack inside func< > or modify Line A only?
#include <iostream>
using namespace std;
void func()
{
cerr << "EMPTY" << endl;
}
template <class A, class ...B> void func()
{
cerr << "A: " << endl;
func<B... >(); // line A
}
int main(void)
{
func<int,int>();
return 0;
}
An expected output :
A:
A:
edited:
all of answers are very good. thanks alot
Sometimes it's easier to unpack everything at once, instead of recursively. If you simply want a parameter pack for_each, you can use a variant of the braced-init-list expansion trick (Live demo at Coliru):
template <class A>
void process_one_type() {
cerr << typeid(A).name() << ' ';
}
template <class ...B> void func()
{
int _[] = {0, (process_one_type<B>(), 0)...};
(void)_;
cerr << '\n';
}
By using func<B... >(); you are implying that func is a function template, but your previously defined func() is not.
You need to define a func() template that accepts zero template arguments. Here's a working example (on g++ 4.8.1):
#include <iostream>
using namespace std;
void func()
{
cerr << "EMPTY" << endl;
}
template <class ... B>
typename std::enable_if<sizeof...(B) == 0>::type func()
{
}
template <class A, class ...B> void func()
{
cerr << "A: " << endl;
func<B... >(); // line A
}
int main(void)
{
func(); // This outputs EMPTY
func<int,int>(); // This will not output EMPTY
return 0;
}
Try this:
template <class A> void func()
{
cerr << "A: " << endl;
}
template <class A, class B, class ...C> void func()
{
cerr << "A: " << endl;
func<B, C...>(); // line A
}
Consider what the invocation of the recursive call func<B...>(); looks like when B... is empty. It's calling func<>(); but the definition of your attempted base case func() is not a template function, ie. you can't call it via func<>();
Since we don't have partial specialization for function templates yet, (hopefully it will be supported soon) one way to do it is to use a class template to do the partial specialization and use the function to simply delegate the work to the class template.
#include <iostream>
/* Forward declaration. */
template <typename... T>
struct FuncImpl;
/* Base case. */
template <>
struct FuncImpl<> {
void operator()() const {
std::cout << "Base case" << std::endl;
}
}; // FuncImpl<>
/* Recursive case. */
template <typename First, typename... Rest>
struct FuncImpl<First, Rest...> {
void operator()() const {
std::cout << "Recursive case" << std::endl;
FuncImpl<Rest...>()();
}
}; // FuncImpl<First, Rest...>
/* Delegate function. */
template <typename... T>
void Func() {
FuncImpl<T...>()();
}
int main() {
Func<>();
Func<int, double>();
}
Personally I think this solution is cleaner than other solutions such as tagged dispatching or SFINAE, despite the cruft around operator()s.
Can I use variadic templates without using the template parameters as function parameters?
When I use them, it compiles:
#include <iostream>
using namespace std;
template<class First>
void print(First first)
{
cout << 1 << endl;
}
template<class First, class ... Rest>
void print(First first, Rest ...rest)
{
cout << 1 << endl;
print<Rest...>(rest...);
}
int main()
{
print<int,int,int>(1,2,3);
}
But when I don't use them, it doesn't compile and complains about an ambiguity:
#include <iostream>
using namespace std;
template<class First>
void print()
{
cout << 1 << endl;
}
template<class First, class ... Rest>
void print()
{
cout << 1 << endl;
print<Rest...>();
}
int main()
{
print<int,int,int>();
}
Unfortunately the classes I want to give as template parameters are not instantiable (they have static functions that are called inside of the template function).
Is there a way to do this?
template<class First> // 1 template parameter
void print()
{
cout << 1 << endl;
}
#if 0
template<class First, class ... Rest> // >=1 template parameters -- ambiguity!
void print()
{
cout << 1 << endl;
print<Rest...>();
}
#endif
template<class First, class Second, class ... Rest> // >=2 template parameters
void print()
{
cout << 1 << endl;
print<Second, Rest...>();
}
Make it a type.
template <typename... Ts>
struct print_impl;
template <typename T>
struct print_impl<T> {
static void run() {
std::cout << 1 << "\n";
}
};
template <typename T, typename... Ts>
struct print_impl<T, Ts...> {
static void run() {
std::cout << 1 << "\n";
print_impl<Ts...>::run();
}
};
template <typename... Ts>
void print() {
print_impl<Ts...>::run();
}
int main() {
print<int, int, int>();
return 0;
}
template <class T, bool flag>
class A
{
//...
void f()
{
std::cout << "false" << std::endl;
}
//...
};
template<class T>
void A<T, true>::f<T, true>()
{
std::cout << "true" << std::endl;
}
The code above is wrong and don't compile, but you get the idea of what I'm going to do. So how should I do that?
You can't specialize just one method of a class. Usually you can solve that with a template nested class on the same T.
template <class T, bool flag>
class A
{
//...
template <class Q, bool flag>
class F_Helper
{
void operator()()
{
std::cout << "false" << std::endl;
}
};
template <class Q>
class F_Helper<Q, true>
{
void operator()()
{
std::cout << "true" << std::endl;
}
};
F_Helper<T> f;
//...
};
Obviously a bit more boilerplate is needed if you do need access to the enclosing class' this pointer.
Contrary to what the other answers say, you can specialize a member function of a class template. But you need to provide all template arguments
template<>
void A<int, true>::f()
{
std::cout << "true" << std::endl;
}
What you try is not valid:
template<typename T>
void A<T, true>::f()
{
std::cout << "true" << std::endl;
}
Partially specializing a member of a class template for particular arguments of that class template is not valid, so that means "define the member function 'f' of a partial specialization of A for <T, true>". Because there is no such partial specialization, the compiler will error out.
If you cannot provide all arguments, you can overload f as follows
template <class T, bool flag>
class A
{
template<typename, bool> struct params { };
void f()
{
f(params<T, flags>());
}
template<typename U>
void f(params<U, true>) {
std::cout << "true" << std::endl;
}
template<typename U, bool flag1>
void f(params<U, flag1>) {
std::cout << "dunno" << std::endl;
}
};
You can specialize whole template class - Ideone link
#include <iostream>
template <class T, bool flag>
class A
{
//...
void f()
{
std::cout << "false" << std::endl;
}
//...
};
template<class T>
class A<T, true>
{
//...
void f()
{
std::cout << "true" << std::endl;
}
//...
};
You need to specialize the whole class:
#include <iostream>
template <class T, bool flag>
class A
{
public:
void f()
{
std::cout << "false" << std::endl;
}
};
template<class T>
class A<T,true>
{
public:
void f()
{
std::cout << "true" << std::endl;
}
};
void main()
{
A<int, false> a;
a.f();
A<int, true> b;
b.f();
}