Syntax error in C++ template member function - c++

I'm new to C++ and would like to get some help with fixing the following template function code without removing the function fl()
template<type T>
class Test
{
int f1(T* x);
};
template< T>
int Test::f1(T* x)
{
return 5:
};

You have numerous syntax errors, but I guess your main issue is you need Test<T>::f1 instead of Test::f1:
//typename, not type
template<typename T>
class Test
{
int f1(T* x);
};
// forgot typename
template<typename T>
int Test<T>::f1(T* x)
//need ^^^
{
return 5;
}
//^ no semicolon

The correct syntax would be
template<typename T>
class Test
{
int f1(T* x);
};
template<typename T>
int Test<T>::f1(T* x)
{
return 5;
};
Note the keyword specifying the template argument T is either typename or class

Related

How to pass structure with template variable as an argument inside member function of class in c++?

I would like to pass 'structure with template variable' as an argument inside member function of class. I am getting error "no matching function for call to". Can anyone help me? I am doing some mistake either in declaration / definition / while passing argument from the main.
template <typename T>
struct msg_1{
int var_1;
int var_2;
T *var_3;
};
template<typename T>
struct msg_2{
int var_1;
int var_2;
T *var_3;
};
class A
{
public:
int a;
int b;
template <typename T>
void test(T *, T *);
};
template <typename T>
void A::test(T *t1, T *t2)
{ cout<<"Inside test #todo Do something"; }
int main()
{
A ob;
ob.a=10;
ob.b=20;
msg_1<int> *ob_1 = new msg_1<int>;
msg_2<int> *ob_2 = new msg_2<int>;
ob.test(ob_1,ob_2);
return 0;
}
========
I have accepted the given suggestion and modified the code, but getting some error while implementing. Kindly have a look.
I have passed the structure as a parameter in test method like below
template <typename T>
struct msg1{
…
};
template<typename U>
struct msg2{
…
};
struct msg3
{
uint16_t var_4;
};
class A
{
public:
int a;
int b;
template <typename T, typename U>
void test(msg1<T> *t1, msg2<U> *t2);
};
template <typename T, typename U>
void A::test(msg1<T> *t1, msg2<U> *t2)
{
cout<<"Inside test #todo Do something";
}
int main()
{
A ob;
ob.a=10;
ob.b=20;
msg_1<msg3> *ob_1 = new msg_1<msg3>;
msg_2<msg3> *ob_2 = new msg_2<msg3>;
ob.test(ob_1,ob_2);
return 0;
}
When I am running above code in online compiler then it’s running fine but when I am implementing it in actual code to do testing then I am getting compile time error
“undefined reference to ‘void A::test< msg3, msg3 > ( msg1 *, msg2 * )’.
Can anyone please tell me what possibly I am doing wrong.
Your template function A::test is only templated with one type T and requires that both parameters have the same type T*. In your example you pass different parameters: msg_1<int> * and msg_2<int> *.
If you really want test to only accept two parameters with identical type, then you can't pass ob_1 and ob_2. If you want test to accept two parameters of different type, then you can change your class A and function A::test as follows.
class A
{
public:
int a;
int b;
template <typename T1, typename T2>
void test(T1 *, T2 *);
};
template <typename T1, typename T2>
void A::test(T1 *t1, T2 *t2)
{ cout<<"Inside test #todo Do something"; }

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)

Declaring function templates before defining when overloading

C++ Primer 5th Edition has a snippet of advice at the end of chapter 16.3 (a chapter discussing function template overloading):
Declare every function in an overload set before you define any of the
functions. That way you don’t have to worry whether the compiler will
instantiate a call before it sees the function you intended to call.
So is this telling me that in choosing the candidate and viable functions during overload resolution it is possible the compiler might instantiate a function template that isn't chosen in the end? I tried to see whether this might actually happen:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <typename T> void test(T*) { }
int main(){
int *q = nullptr;
test(q); //test(T*) should be the best match
}
This program would throw a compiler error if test(T const &) was instantiated in any form, except the program compiles fine as expected. So what kind of compilation mishap is that tip trying to guard me from? When would it ever instantiate a function before it saw the function I was trying to call?
The author is warning you of this:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
int main(){
int *q = nullptr;
test(q); //test(T*) will not be matched.
}
template <typename T> void test(T*)
{
}
And these:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <> void test<int>(int const &);
void test(int *);
int main(){
int *q = nullptr;
test(q); //test(int*) should be the best match
int a;
test(a); // test<int>(int const&) should be the best match
}
template <> void test<int>(int const &)
{
}
void test(int *)
{
}
If you don't provide declarations of
template <> void test<int>(int const &);
void test(int *);
before main, they won't be matched in main.
I've seen plenty of SO questions that is some variation of
template<class T, class... Ts>
T sum(T t, Ts... ts) { return t + sum(ts...); }
// ^ |
// |--------------------------------
// only one visible in
// definition context
template<class T>
T sum(T t) { return t; }
int main() {
sum(1, 2); // doesn't compile
}
(The return type isn't perfect, but you get the idea.)
And then people are surprised when it doesn't compile.
Or, even more fun,
template<class T> void f(T t) { f((int)t); }
void f(int) { /*...*/ }
int main() {
f(1L); // infinite recursion
}

C++ template member function already defined with same type

I have this simple code below, a template with 2 type parameters. If I declare my class with the same type (like BidirectionalMap<int,int>), I receive an error:
int BidirectionalMap<T,S>::operator [](T) const' : member function already defined or declared
Here's my template code:
template <class T, class S>
class BidirectionalMap{
int count(T t){
return 1;
}
int count(S s){
return 1;
}
};
The error you got is normal, because after substitution you have
template <>
class BidirectionalMap<int, int>
{
int count(int t){ return 1; }
int count(int s){ return 1; } // Duplicated method
};
To solve that, you may provide partial specialization:
template <class T>
class BidirectionalMap<T, T>
{
int count(T t) { return 1; }
};
In C++20, you might use requires to "discard" methods:
template <class T, class S>
class BidirectionalMap
{
int count(T t) requires(!std::is_same<T, S>::value) { /*..*/ }
int count(S s) requires(!std::is_same<T, S>::value) { /*..*/ }
int count(T t) requires( std::is_same<T, S>::value) { /*..*/ }
};

C++: error "explicit specialization in non-namespace scope"

template<typename T1, typename T2>
class Bimap {
public:
class Data {
private:
template<typename T> Data& set(T);
template<> Data& set<T1>(typename T1 v) { /*...*/ }
};
};
That gives me the error:
error: explicit specialization in non-namespace scope 'class Bimap<T1, T2>::Data'
I understand what the error is saying. But why I can't I do this? And how can I fix it?
One way forget templates, overload:
Data& set(T1 v) { /*...*/ }
but here is a trick which I use sometimes
you can specialize class template within class:
class {
template<typename T>
struct function_ {
static void apply(T);
};
template<>
struct function_<int> {
...
};
template<typename T>
void function(T t) { return function_<T>::apply(t); }
#Albert
I had a similar problem when I wanted to add a "trim-excess-capacity" to a custom made container. The std::vector swap trick and changing the declaration of the existing container were not valid options. So I've come up with this:
template <class T, bool isPtr> struct DeleteImp
{
static void Trim(T* to, unsigned int count);
};
template <class T> struct DeleteImp<T, false>
{
static void Trim(T* to, unsigned int count) {}
};
template <class T> struct DeleteImp<T, true>
{
static void Trim(T* to, unsigned int count)
{
for(unsigned int i=0; i<count; i++)
delete to[i];
}
};
used by my container like this:
DeleteImp<T, TypeTraits<T>::isPointer>::Trim(buf + length, truelength-length);
You may also want to check out this resource.