This question already has an answer here:
Member function template of class template can't find definition despite explicit instantiation present. Doesn't link
(1 answer)
Closed 3 years ago.
How do you instantiate a template member function of a template class without making a dummy call to it?
So imagine a header: class.h
#pragma once
template<class T>
class A {
public:
template<class R>
T b(R r);
};
class.cc
#include <limits>
#include "class.h"
template<class T> template<class R> T A<T>::b(R r)
{
/* Some code */
return std::numeric_limits<R>::max() - r;
}
void dummy()
{
A<int> a;
a.b<short>(2);
}
And some test file:
#include <iostream>
#include "class.h"
using namespace std;
int main(){
A<int> a{};
auto ans = a.b<short>(2);
cout << ans << " " << sizeof(ans) << endl;
}
How do I force the compiler to compile A<int>::b<short>(short) without calling it in class.cc (and thus having a dummy function laying around) or putting everything in the header (and having to recompile alot of code all the time).
I've tried different forms of template A<int>; and template <> template <> int A<int>::b(short) in the cc-file but I can't make up the right syntax.
You can do it with this:
template int A<int>::b<short>(short r);
Related
This question already has answers here:
Class template argument deduction not working with alias template
(2 answers)
Closed 7 months ago.
In this piece of code:
#include <iostream>
#include <vector>
#include <utility>
template <typename T>
using Separation = std::pair<std::vector<T>, std::vector<T>>;
int main()
{
std::vector<int> vector1 = {1};
Separation s1(vector1, vector1);
std::cout << s1.first[0];
return 0;
}
The g++ compiler says: error: missing template arguments before ‘(’ token
That can be fixed just by adding the template parameter to Separation. But, if v1 is a vector of integer, shouldn't the compiler be able to understand that T should be generic that comes from the vector??
If you can make it a subtype, you may add a deduction guide:
#include <iostream>
#include <vector>
#include <utility>
template <typename T>
struct Separation : std::pair<std::vector<T>, std::vector<T>> {
using std::pair<std::vector<T>, std::vector<T>>::pair;
};
template <class T>
Separation(std::vector<T>, std::vector<T>) -> Separation<T>;
int main()
{
std::vector<int> vector1 = {1};
Separation s1(vector1, vector1); // works fine
std::cout << s1.first[0];
return 0;
}
I have a template class class_A:
// class_A.h
#pragma once
#include <iostream>
#include <tuple>
template <class T>
class class_A
{
public:
class_A(){}
T Function_A(T parameter)
{
return parameter;
}
};
that I am trying to use in a non-template class class_B as private member:
// class_B.h
#pragma once
#include <tuple>
#include <iostream>
#include "class_A.h"
class class_B
{
public:
class_B();
template <typename T> T Evaluate(T parameter);
private:
std::tuple<class_A<double>, class_A<char> > As;
};
and
// class_B.cc
#include "class_B.h"
class_B::class_B(){}
template <typename T>
T class_B::Evaluate(T parameter)
{
return std::get<class_A<T>>(As).Function_A(parameter); //This is causing error
//return parameter // This works
}
template double class_B::Evaluate(double parameter);
template char class_B::Evaluate(char parameter);
and my main.cc is:
// main.cc
#include<iostream>
#include <string>
#include "class_B.h"
using namespace std;
int main()
{
class_B B;
std::cout<< B.Evaluate(5.2) <<std::endl;
std::cout << B.Evaluate('h') << std::endl;
return 0;
}
I get the following error:
src/class_B.cc:8:12: error: no matching function for call to 'get'
return std::get<class_A<T>>(As).Evaluate(parameter);
.
.
.
etc.
This is a trial of the answer: https://stackoverflow.com/a/55357742/9203360 that didn't work, but would be ideal if it did.
As I mentioned in the comments, the overload of std::get taking a type as template argument and returning the tuple element of that type is available only since C++14.
Per your comment you were not compiling against C++14 or later and so there was no match for std::get with a type as first template argument.
The
std::get< class_A< T>>(As)
get an instance of class_A, so you can't call the Evaluate Method, doesn't exist. You should call method Function_A, or define Evaluate method in class_A
return std::get<class_A<T>>(As).Function_A(parameter); // Call Function_A
It works in Visual Studio 2015 - Windows Platform 10.0.17763.0
Plus you need c++14 for std::get to work.
Why are we suppose to use template parameters at front of every function even if we are not using deduced template parameters in the function. As we can see that i am not using template parameter _T in printP() function (around 30) then why it is required to include template syntax at front of this function.
NOTE: This is very simplified version of my big class, and it might look silly because it is very small but, consider a situation where you are using template for only few [2-3] function of your class but you are bound to type (even copy past) this lengthy template syntax at front of every function but i am asking why??.
Is there any way to get of this
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
template<typename _T>
class Thing{
int _p;
_T _k;
public:
Thing(int p, _T k):_p(p),_k(k){}
void printK();
void printP();
};
template<typename _T>
void Thing<_T>::printK(){
cout << _k << endl;
}
template<typename _T>
void Thing<_T>::printP(){
cout << _p << endl; // as we can see that i am not using template paramerter "_T"
} // here in this function then why it is required to include template syntax
int main()
{
Thing<int> a(1,2);
a.printK();
a.printP();
}
Because the function PrintK is member of template class Thing<_T>. For a member function definition outside the class, the function name also includes class name(to which it belongs, here it belongs to Thing), since Thing is template, so function name requires you to provide template parameter (T here).
e.g.
Function definition outside class requires the following syntax
**
return type class name:: function name (argument list)
*
Here class (Thing) is template class, so its name will also require type (like Thing<_T>).
I hope you got my point.
Its usually a good idea to restrict the members and functions of a template class to those that are dependent on the template parameters. Non-dependent members and functions can be put in a separate non=template class (is there a better name?). For example:
#include <iostream>
using namespace std;
class ThingBase
{
public:
ThingBase(int p)
: _p(p)
{
}
void printP();
protected:
int _p;
};
void ThingBase::printP(){
cout << _p << endl;
}
template<typename _T>
class Thing : public ThingBase {
_T _k;
public:
Thing(int p, _T k)
: ThingBase(p),
_k(k){}
void printK();
};
template<typename _T>
void Thing<_T>::printK(){
cout << _k << endl;
}
int main()
{
Thing<int> a(1,2);
a.printK();
a.printP();
}
#include <string>
#include <iostream>
using namespace std;
template <class T>
class Tyler{
T first, second;
public:
Tyler(T a, T b)
{
first = a;
second = b;
}
int larger();
string larger();
};
template <class T>
int Tyler<int>::larger()
{
cout << "int larger" <<endl;
return(first>second?first:second);
}
template <class T>
string Tyler<string>::larger()
{
cout << "string larger" <<endl;
if(first.compare(second) > 0)
return(first);
return(second);
}
int main()
{
Tyler<int> tobj(7,77);
Tyler<string> tstr("Seven", "test");
cout << tobj.larger() <<endl;
cout << tstr.larger() <<endl;
}
I am learning C++ (templates in particular) and trying to understand. What if I wanted to create the two functions below and the "larger" function will perform different depending on which datatype is specified in the class instantiated in main. I have only seen examples that use int and float.
First, you appear to be trying to specialize the function, so your declarations are not right. You should have this declaration.
T larger();
You want each Tyler object to have only a single larger function, that does different things depending on T. Next, the definitions:
int Tyler<int>::larger()
Here, you're creating a template specialization. It's a template function (well, sort of), so it does need the template bit atop it, but this specialization requires no template parameters, so...
template<>
int Tyler<int>::larger()
Why is that useful? Well, because sometimes a specialization can have template parameters...
template<class T, class Allocator>
vector<T,Allocator> Tyler< vector<T,Allocator> >::larger()
The following code works fine, a simple template class with a definition and a use
#include <string>
#include <iostream>
using namespace std;
template<class T> class foo{
public:
string what();
};
template<class T> string foo<T>::what(){
return "foo of type T";
}
int main(){
foo<int> f;
cout << f.what() << endl;
}
If I then add the following (above main, but after the declaration of template class foo;)
template<> class foo<char>{
public:
string what();
};
template<> string foo<char>::what(){
return "foo of type char";
}
I get an error from g++
Line 19: error: template-id 'what<>'
for 'std::string foo::what()'
does not match any template
declaration
Here is a codepad the shows the error: http://codepad.org/4HVBn9oJ
What obvious misstake am I making? Or is this not possible with c++ templates?
Will defining all the methods inline (with the defintion of template<> foo) work?
Thanks again all.
template<> class foo<char>{
public:
string what();
};
/*template<>*/ string foo<char>::what(){
return "foo of type char";
}
You don't need that template<>. foo<char> is already a complete type after it's specialized.
Writing this as:
#include <string>
#include <iostream>
using namespace std;
template<class T> class foo{
public:
string what();
};
template<class T> string foo<T>::what(){
return "foo of type T";
}
template<> class foo<char>{
public:
string what();
};
string foo<char>::what(){
return "foo of type char";
}
int main(){
foo<char> f;
cout << f.what() << endl;
}
works as expected.
If I then add the following (above main, but before the declaration of template class foo;)
Define the specialization after the generic class template.
By the time the compiler sees the specialization, it first needs to know the class template of which this is a specialization. So logically, the specialization should appear after the generic class template.