Calling a templated member of a class - c++

I've written a class that has a templated member function, mostly because it takes a std::vector as an argument, however I'm struggling to find a proper way to call it.
class foo(){
// ...
template <typename _t> int bar(const std::vector<_t> *values);
// ...
}
when calling this function later with:
// ...
foo c;
std::vector<int> v(5,100);
c.bar(&v);
// ...
I get the error:
error: no matching function for call to ‘foo::bar(std::vector<int>*)’
c.bar(&v);
Shouldn't foo::bar(std::vector<int>*) conform to the template parameters? Why won't it compile?

Working example:
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values) {
return 1;
}
};
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}
If you really need it to not to be inline you can:
//from here
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values);
};
template <typename _t> int foo::bar(const std::vector<_t> *values) {
return 0;
}
//to here - should be in header file to allow compiler to link it!
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}

Related

Template member function specialization of a templated class without specifying the class template parameter

What is the correct syntax to specialize a templated member function of a templated class without specifying the class template parameter?
Here is what I mean:
Example #1 (works):
#include <iostream>
struct C1
{
template <class B>
void f(void) const;
};
template <>
void C1::f<int>(void) const { std::cout<<777<<std::endl; }
int main(void)
{
C1 c1; c1.f<int>();
}
Example #2 (works):
#include <iostream>
template <class A>
struct C2
{
template <class B>
void f(void) const;
};
template <>
template <>
void C2<int>::f<int>(void) const { std::cout<<888<<std::endl; }
int main(void)
{
C2<int> c2; c2.f<int>();
return 0;
}
Example #3 (does not compile: "enclosing class templates are not explicitly specialized"):
#include <iostream>
template <class A>
struct C3
{
template <class B>
void f(void) const;
};
struct D { static int g(void){ return 999; } };
template <class A>
template <>
void C3<A>::f<int>(void) const { std::cout<<A::g()+1<<std::endl; }
template <class A>
template <>
void C3<A>::f<char>(void) const { std::cout<<A::g()+2<<std::endl; }
int main(void)
{
C3<D> c3a; c3a.f<int >(); // expect to see 1000
C3<D> c3b; c3b.f<char>(); // expect to see 1001
return 0;
}
How can I make example #3 work?
You can use a technique called tag dispatch and replace the template specialisations by function overloads.
template<typename>
struct Tag {};
template <class A>
struct C3
{
void f_impl(Tag<int>) const;
void f_impl(Tag<char>) const;
template<class B>
void f() const {
f_impl(Tag<B>{});
}
};
struct D { static int g(void){ return 999; } };
template <class A>
void C3<A>::f_impl(Tag<int>) const { std::cout<<A::g()+1<<std::endl; }
template <class A>
void C3<A>::f_impl(Tag<char>) const { std::cout<<A::g()+2<<std::endl; }
Then your call site looks exactly as you want:
C3<D> c3; c3.f<int>(); // expect to see 1000
C3<D> c4; c4.f<char>(); // expect to see 1001
Full example here.

How does one specialize a template for all non-array types?

Let's say I have a template my_type. I want it to have general functionality, to have a few extra functions when T is not an array and to have others when T is an array.
Let's say I have the following template:
template <typename T>
class my_class<T> {
public:
int f1(); // This function is available for all T
int f2(); // This function is available when T is not an array
int f3(); // This function is available when T is an array
}
So if I try:
my_class<int> c1; my_class<int[3]> c2;
c1.f1(); c2.f1(); // both fine
c1.f2(); c2.f3(); // both fine
c1.f3(); c2.f2(); // both should give a compile error
I am aware std::unique_ptr does this internally. So how does it do it?
Another way, using enable_if. Note also the use of a base class to capture all common behaviour.
#include <type_traits>
template<class T>
struct my_base
{
int f1();
};
template<class T, typename Enable = void>
class my_class;
template<class T>
class my_class<T, std::enable_if_t<std::is_array<T>::value>>
: public my_base<T>
{
public:
int f3(); // This function is available when T is an array
};
template <typename T>
class my_class<T, std::enable_if_t<not std::is_array<T>::value>>
: public my_base<T>
{
public:
int f2(); // This function is available when T is not an array
};
int main()
{
auto a = my_class<int[]>();
a.f1();
// a.f2();
a.f3();
auto na = my_class<int>();
na.f1();
na.f2();
// na.f3();
}
I have figured it out myself. The following code will do the exact thing I have asked for.
template<typename T>
class my_class {
public:
int f1() { return 1; }
int f2() { return 2; }
};
template<typename T>
class my_class<T[]> {
public:
int f1() { return 1; }
int f3() { return 3; }
};
Note that the implementation of the common function (f1) had to be copied. Now is there a way to use a single implementation? (note that it is NOT as simple as a return 1; like in the example code and thus I can't separate functionality into a non-template function)

How do I format my function to call a templated class?

I'm sure there is a very easy answer, but I can't figure it out. I have written a templated class, but I want to pass that class by reference in a class function that isn't templated. Heres what I have. I get a bunch of errors. All I need to do is figure how to format the way to insert templated class into function, but I'm at a lost. Thank you and sorry if the code doesn't really help you out.
#include <iostream>
using namespace std;
template <typename T>
class Foo {
public:
Foo();
insert(const T& Item)
//And other function, just examples
};
class noFoo(){
void test(Foo <T>& foo);
int i;
int j;
int k
};
template <typename T>
void noFoo::test(Food <T>& foo)}
cout << "hi";
}
int main() {
Foo<char> wr;
test(wr);
return 0;
}
Make test a function template. I also corrected loads of syntax errors for you (class noFoo()?), removed unnecessary code, and ran clang-format for indentation.
#include <iostream>
template <typename T>
class Foo {};
class noFoo
{
public:
template <typename T>
void test(Foo<T> &);
};
template <typename T>
void noFoo::test(Foo<T> &)
{
std::cout << "hi\n";
}
int main()
{
Foo<char> wr;
noFoo{}.test(wr);
}
Since your question is tagged d, here the same code in D.
import std.stdio;
class Foo(T) {};
class noFoo
{
public:
void test(T)(Foo!(T))
{
writeln("hi");
}
};
void main()
{
auto wr = new Foo!char;
(new noFoo).test(wr);
}

C++ template, static function specialization

I have a syntax error with my template
I would like to partial specialize a static function of my template class
class.hpp
template <typename Foo, size_t bar = 26>
class MyClass
{
MyClass();
static void function();
};
#include "class.tpp"
class.tpp
template <typename Foo, bar>
MyClass<Foo, bar>::MyClass()
{ }
template <typename Foo>
inline
void
MyClass<Foo, 6>::function()
{
// ...
}
template <typename Foo>
inline
void
MyClass<Foo, 26>::function()
{
// ...
}
error: template definition of non-template
I just want to implement MyClass<Foo, bar>::function for bar == 26 and bar == 6
How to do that properly ?
Thanks
The function is not a template itself, it is only inside a class template. You can specialize the class for those cases, but not the function itself.
template <class Foo>
class MyClass<Foo, 26>
{
static void function() { ... }
};
Provided you have specialized the class like so, you can only declare the function inside the class, and define it outside like so:
template <class Foo>
void MyClass<Foo, 26>::function() { ... }
If you don't specialize it beforehand, you'll get a compilation error for using an incomplete type.
You might also find this question and answer on specializing a single function inside a class template relevant.
You cannot partial specialize method like that.
You may partial specialize the whole class.
or as alternative, you may forward the implementation to some helper:
struct that you may specialize as you want.
overload (using some dispatching):
namespace detail
{
template <typename Foo, std::size_t bar>
void function_impl(MyClass<Foo, bar>& that)
{
// Generic case.
}
template <typename Foo>
void function_impl(MyClass<Foo, 6>& that)
{
// special case <Foo, 6>.
}
template <typename Foo>
void function_impl(MyClass<Foo, 26>& that)
{
// special case <Foo, 26>.
}
}
template <typename Foo, std::size_t bar>
inline
void
MyClass<Foo, bar>::function()
{
detail::function_impl(*this);
}
After doing some research; Partial Specialization for member functions of a class template are not allowed, so one would have to specialize the whole class which can be a problem if the actual class is quite large. If you are trying to separate the implementation from the declaration having a wrapper or helper will work, but you must defined that and the partial specialization first. Check out this code here for it compiles, builds and outputs the appropriate values using MSVC 2015 CE.
MyClass.h
#ifndef MY_CLASS_H
#define MY_CLASS_H
#include <iostream>
// Helper - Wrapper Class
template<typename Foo, size_t Bar>
class specialized {
public:
inline static void function();
};
// Partial Specialization
template<typename Foo>
class specialization<Foo, 6> {
public:
inline static void function();
};
// Actual Class
template<typename Foo, size_t Bar = 26>
class MyClass {
private:
specialized<Foo, Bar> func;
public:
MyClass();
inline void function(); // Works
// inline static void function(); // Compiler Error
}; // MyClass
#include "MyClass.inl"
#endif // MY_CLASS_H
MyClass.inl
// Helper - Wrapper
template<typename Foo, size_t Bar>
inline void specialized<Foo, Bar>::function() {
std::cout << "26" << std::endl;
} // function
// Specialized
template<typename Foo>
inline void specialized<Foo, 6>::function() {
std::cout << "6" << std::endl;
} // function
// Constructor
template<typename Foo, size_t Bar>
MyClass<Foo, Bar>::MyClass() {
} // MyClass
// Class Member Function
template<typename Foo, size_t Bar>
inline void MyClass<Foo, Bar>::function() {
func.function();
} // function
MyClass.cpp
#include "MyClass.h"
Main.cpp
#include "MyClass.h"
int main() {
MyClass<float, 6> a;
a.function(); // Prints Out 6
MyClass<float, 26> b;
b.function(); // Prints Out 26
MyClass<float> c;
c.function(); // Prints Out 26
MyClass<float, x != 6> d;
d.function(); // Prints Out 26
return 0;
} // Main

partial specified template class with nontype parameter in C++

In following code, I got an compiling error
#include <iostream>
using namespace std;
template <typename T, int I>
class MyClass {
public:
void func1(){
cout<<"default: func1"<<endl;
}
void func2(){
cout<<"default: func2"<<endl;
}
private:
T haha;
};
template <typename T>
void MyClass<T, 1>::func1(){
cout<<"special: func1"<<endl;
};
int main()
{
MyClass<int, 2> intclass;
intclass.func1();
intclass.func2();
MyClass<double, 1> doubleclass;
doubleclass.func1();
doubleclass.func2();
return 0;
}
I got following compiling error:
partialspecifizednontype.cpp:19: error: invalid use of incomplete type 'class MyClass<T, 1>'
partialspecifizednontype.cpp:6: error: declaration of 'class MyClass<T, 1>'
Any specific reason that I can't do this? Is there any workaround to achieve this?
I notice that if my template class don't have first parameter things are OK. (my gcc is 4.2.1)
Following example is OK:
#include <iostream>
using namespace std;
template <int I>
class MyClass {
public:
void func1(){
cout<<"default: func1"<<endl;
}
void func2(){
cout<<"default: func2"<<endl;
}
};
template<>
void MyClass<1>::func1(){
cout<<"special: func1"<<endl;
};
int main()
{
MyClass<2> intclass;
intclass.func1();
intclass.func2();
MyClass<1> doubleclass;
doubleclass.func1();
doubleclass.func2();
return 0;
}
Member functions of class templates are also function templates in their own right. That means that you can specialize them explicitly (as you do in your second example), but function templates cannot be specialized partially (as you are trying in your first example).
As a workaround, you can specialize the entire class partially:
template <typename T>
class MyClass<T, 1>
{
public:
void func1() { cout << "special: func1" << endl; };
// ...
};
You may need to refactor your code to put common code into a base class to make this approach maintainable.