I have header file and in my header file I make a template and I want to use the template just on one function and not force all other functions. Is it possible to get the type before the function like i did in main?
This is an example:
TestTemp.h
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template<class T>
class TestTemp
{
public:
TestTemp();
void SetValue( int obj_i );
int Getalue();
void sum(T b, T a);
private:
int m_Obj;
};
#include "TestTemp.cpp"
#endif
TestTemp.cpp
//TestTemp.cpp
include<TestTemp.h>
TestTemp::TestTemp()
{
}
void TestTemp::SetValue( int obj_i )
{
m_Obj = obj_i ;
}
int TestTemp::GetValue()
{
return m_Obj ;
}
template<class T>
void TestTemp<T>::sum(T b, T a)
{
T c;
c = b + a;
}
main.cpp
//main.cpp
include<TestTemp.h>
void main()
{
TestTemp t;
t.sum<int>(3,4);
}
Have any ideas?
Your TestTemp is a template class already, no need to make sum template function.
TestTemp<int> t;
t.sum(3, 4);
If you really want to make sum function a template function of TestTemp:
template<class T>
class TestTemp
{
public:
//....
template<typename U>
void sum(U b, U a);
private:
int m_Obj;
};
To implement it outside template class:
template<class T>
template<typename U>
void TestTemp<T>::sum(U b, U a)
{
T c;
c = b + a;
}
int main()
{
TestTemp<int> t;
t.sum<int>(3, 4);
}
However, I feel you just need a free template function
template<typename T>
T sum(T a, T b)
{ return a + b; }
// TestTemp.h
#ifndef _TEST_TEMP_H_
#define _TEST_TEMP_H_
class TestTemp
{
public:
TestTemp();
void SetValue( int obj_i );
int Getalue();
template<class T>
void sum(T b, T a);
private:
int m_Obj;
};
TestTemp::TestTemp() {}
void TestTemp::SetValue( int obj_i )
{
m_Obj = obj_i ;
}
int TestTemp::Getalue()
{
return m_Obj ;
}
template<class T>
void TestTemp::sum(T b, T a)
{
T c;
c = b + a;
}
#endif
//main.cpp
#include <TestTemp.h>
int main()
{
TestTemp t;
t.sum<int>(3,4);
return 0;
}
What you need is a normal class which has a template member function.
It's not a god idea to include an cpp file in header file. For template functions, just put it in header file.
You should take a look here. There are many examples.
I think it should work as you expect it if you just remove
template<class T>
from the
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
--> template<class T> <--
class TestTemp
block. You don't have to define the whole class as templated when you just want a method to have template parameters.
You just need to define TestTemp as normal class of which "sum" is a template function. Then in your function "main" (i.e. the caller), the template argument will be deduced from the function arguments.
class TestTemp
{
public:
TestTemp();
void SetValue(int obj_i);
int Getalue();
template<class T>
void sum(T b, T a);
private:
int m_Obj;
};
TestTemp::TestTemp() {}
void TestTemp::SetValue(int obj_i)
{
m_Obj = obj_i;
}
int TestTemp::Getalue()
{
return m_Obj;
}
template<class T>
void TestTemp::sum(T b, T a)
{
T c;
c = b + a;
}
//main.cpp
int main()
{
TestTemp t;
t.sum(3, 4);
return 0;
}
Related
i have this class
template <typename T>
class B{
T x;
public:
B(char c){
if(typeid(x)==typeid(char)) x=c;
else{
string h;
for(int i=0;i<10;i++) h.push_back(c);
x=h;
}
}
};
it is a sample class, if the type of x is char i want x=c while if x is a string i want x to be [c]^10
then i try to create two objects:
int main(){
B<string> a('f');
B<char> b('g');
}
when i object b is instantiated, the compiler generates an error on the line 10 :
[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'char' in assignment
i understand the error comes from the fact that you cant assign a string to a char, but i need the task done anyways, how can i do it?
With C++17, you might use if constexpr:
template <typename T>
class B
{
T x;
public:
explicit B(char c)
{
if constexpr (std::is_same_v<T, char>) {
x = c;
} else {
// static_assert(std::is_same_v<T, std::string>);
x = std::string(10, c);
}
}
};
Pre C++17, this seems like the easiest possibility:
#include <string>
template<class T>
class B {
T x;
public:
B(char c);
};
template<>
B<char>::B(char c) : x(c) {}
template<>
B<std::string>::B(char c) : x(std::string(c,10)) {}
int main() {
B<char> a('a');
B<std::string> b('b');
//B<int> c('c'); // Linker error
}
if the type of x is char i want x=c while if x is a string i want x to be [c]^10
One way to do that would to be to create a function template that returns the right object.
// Declare the function template.
template <typename T> T make_data(char c);
Define specializations of the function template.
template <> char make_data<char>(char c)
{
return c;
}
template <> make_data<std::string>(char c)
{
return std::string(c, 10);
}
Use them to implement B.
template <typename T>
class B
{
T x;
public:
B(char c) : x(make_data<T>(c)) {}
};
Simple old fashioned template specialization:
template <typename T>
class B
{
T x;
public:
explicit B(char c) : x(c)
{}
};
template <>
B<std::string>::B(char c) : x(10, c)
{}
https://wandbox.org/permlink/5klGI0poD9mor4WY
I am trying to overload a template method in a template class. But it will only work if I do it inside the class definition.
How do I get the external implementation outside of the class definition?
template<typename B>
class ClassA {
public:
template<typename T>
void foo( T a );
template<>
void foo( std::string a ) { A = 4; }
template<>
void foo( float a );
B A;
};
template<typename B>
template<typename T>
void ClassA<B>::foo( T a ) { A = a; }
template<typename B>
template<>
void ClassA<B>::foo<float>( float a ) { A = a; }
// Compiler error: unable to match function definition to an existing declaration
void foo() {
ClassA<int> a;
a.foo( 1 );
a.foo<std::string>( "kat" );
a.foo<float>( 4.5f );
}
Since the overloads don't have any template parameters, they aren't templates any more.
template<typename B>
class ClassA {
public:
template<typename T>
void foo( T a );
void foo( std::string a ) { A = 4; }
void foo( float a );
B A;
};
In the version with template<>, they are specializations, not overloads. Overloading, not specialization, is probably what you want.
I wonder whether the below tricky situation is possible:
Suppose I have a template class template <typename DTYPE> class A{};, where DTYPE is supposed to be one of uint8_t, uint16_t, etc. I want to add a friend class to A, but this friend class differs for each DTYPE alternative. Further, suppose the friend classes for different DTYPE values are not instantiations of another template class, but independent classes.
Is there a way to do it?
You can add template "proxy" class FriendOfA and specialize it for whatever type you need:
// actual friends
class FriendUint8 {};
class FriendUint16 {};
template<typename T> struct FriendOfA;
template<>
struct FriendOfA<uint8_t> {
typedef FriendUint8 type;
};
template<>
struct FriendOfA<uint16_t> {
typedef FriendUint16 type;
};
// optional helper
template <typename T>
using FriendOfA_t = typename FriendOfA<T>::type;
template<class T>
class A {
friend typename FriendOfA<T>::type;
// or simply
friend FriendOfA_t<T>;
};
I believe you're looking for something like that:
#include <iostream>
struct BaseFriend
{
template <typename T>
void boo(const T& t) { t.foo(); }
};
struct BaseFriendProxy
{
template <typename T>
void boo(const T& t) { std::cout << "Proxy: "; t.foo(); }
};
template <typename TType>
struct Friend ;
template <>
struct Friend<int> {
using T = BaseFriend;
};
template <>
struct Friend<char> {
using T = BaseFriendProxy;
};
template <typename DTYPE>
class A
{
private:
friend typename Friend<DTYPE>::T;
void foo() const
{ std::cout << "A::foo()" << std::endl; }
};
int main()
{
A<int> a;
BaseFriend bf1;
bf1.boo(a);
A<char> b;
BaseFriendProxy bf2;
bf2.boo(b);
return 0;
}
But this will work only with C++11: you can't combine friend class ... with typename X::Y in C++03
Sure you can, specialize your template and add whatever friend class you want:
#include <iostream>
using namespace std;
class base {
public:
virtual int getValue() = 0;
};
class friend1 {
public:
base* ptr;
int getValue() {
return ptr->getValue();
}
};
class friend2 {
public:
base* ptr;
int getValue() {
return ptr->getValue();
}
};
template <typename DTYPE> class A : public base{
public:
A() { data = 42; }
// No friends
private:
int data;
int getValue() {
return data;
}
};
template <> class A<char> : public base{
public:
A() { data = 44; }
friend class friend1;
private:
int data;
int getValue() {
return data;
}
};
template <> class A<bool> : public base{
public:
A() { data = 45; }
friend class friend2;
private:
int data;
int getValue() {
return data;
}
};
int main()
{
A<char> obj1;
friend1 friend_of_obj1;
friend_of_obj1.ptr = &obj1;
cout << friend_of_obj1.getValue() << endl;
A<bool> obj2;
friend2 friend_of_obj2;
friend_of_obj2.ptr = &obj2;
cout << friend_of_obj2.getValue();
}
http://ideone.com/hM9x0y
Yes, a friend can be based on a template. Such as;
template <typename DTYPE>
struct Friend;
template <class DTYPE>
class A {
friend struct Friend<DTYPE>;
};
For each type DTYPE for the class A you wish to support (different by implementation) you can specialise Friend, such as;
template<>
struct Friend<uint8_t> {
// ...
};
A basic working sample:
#include <cstdint>
using namespace std;
template<typename T>
struct Friend;
template <class T>
class A {
friend struct Friend<T>;
int i = 0;
};
template<>
struct Friend<uint8_t> {
void method() {
A<uint8_t> a;
a.i = 8;
}
};
template<>
struct Friend<uint16_t> {
void method() {
A<uint16_t> a;
//A<uint8_t> b; // fails to compile
a.i = 16;
}
};
int main()
{
A<uint8_t> a;
Friend<uint8_t> f;
f.method();
}
template <typename T, typename C>
class CSVWriter{
template <typename PrinterT>
void write(std::ostream& stream, const PrinterT& printer){
}
};
I want to check whether there exists at least two overloads PrinterT::operator()(T*) and PrinterT::operator()(C*)
PrinterT may or may not inherit from std::unary_function
What concept Checking Classes I need to use here ?
(I am not using C++11)
You can use something like that
#include <iostream>
#include <boost/concept/requires.hpp>
#include <boost/concept/usage.hpp>
template <class Type, class Param>
class has_operator_round_brackets_with_parameter
{
public:
BOOST_CONCEPT_USAGE(has_operator_round_brackets_with_parameter)
{
_t(_p);
}
private:
Type _t;
Param _p;
};
struct X {};
struct Y {};
struct Test1
{
void operator() (X*) const { }
};
struct Test2: public Test1
{
void operator() (X*) const { }
void operator() (Y*) const { }
};
template <class T, class C>
struct CSVWriter
{
template <class PrinterT>
BOOST_CONCEPT_REQUIRES(
((has_operator_round_brackets_with_parameter<PrinterT, T*>))
((has_operator_round_brackets_with_parameter<PrinterT, C*>)),
(void)) write(std::ostream& stream, const PrinterT& printer)
{
}
};
int main()
{
CSVWriter<X, Y> w;
// w.write<Test1>(std::cout, Test1()); // FAIL
w.write<Test2>(std::cout, Test2()); // OK
return 0;
}
Suppose we have a class:
template <class Type>
class A
{
public:
void function1(float a, Type b);
void function1(float a, float b);
};
Now instantiate the class like this:
A<int> a;
It's fine, this class will have 2 overloaded functions with these parameters: (float a, int b); (float a, float b);
But when you instantiate the class like this:
A<float> a;
You get compile error:
member function redeclared.
So, depending on the type of Type, I wan't (or don't want) the compiler to define a function, something like this:
template <class Type>
class A
{
public:
void function1(float a, Type b);
#if Type != float
void function1(float a, float b);
#endif
};
But, of course, the syntax above doesn't work. Is it possible to perform such a task in C++? If possible, please provide an example.
You can use some C++11 std::enable_if :
template <class Type>
class A
{
public:
template<typename t = Type,
typename std::enable_if<!std::is_same<t, float>::value, int>::type = 0>
void function1(float a, Type b) {
}
void function1(float a, float b) {
}
};
You could use template specialization:
template <class Type>
class A {
public:
void function1(float a, Type b) {
}
void function1(float a, float b) {
}
};
template <>
class A<float> {
public:
void function1(float a, float b) {
}
};
// ...
A<int> a_int;
a_int.function1(23.4f, 1);
a_int.function1(23.4f, 56.7f);
A<float> a_float;
a_float.function1(23.4f, 56.7f);
--- EDIT ---
If you have a large number of common functions, you could do something like this:
class AImp {
public:
void function1(float a, float b) {
}
void function1(float a, double b) {
}
void function1(float a, const std::string& b) {
}
// Other functions...
};
template <class Type>
class A : public AImp {
public:
void function1(float a, Type b) {
}
using AImp::function1;
};
template <>
class A<float> : public AImp {
};
// ...
A<int> a_int;
a_int.function1(23.4f, 1);
a_int.function1(23.4f, 56.7f);
a_int.function1(23.4f, 56.7);
a_int.function1(23.4f, "bar");
A<float> a_float;
a_float.function1(23.4f, 56.7f);
a_float.function1(23.4f, 56.7);
a_float.function1(23.4f, "bar");
Use SFINAE:
#include <iostream>
#include <type_traits>
template <typename Type>
struct Foo {
template <typename T = Type>
void function1(float a, float b, typename std::enable_if<!std::is_same<T, float>::value>::type *c = 0) {
std::cout << "float\n";
}
void function1(float a, Type b) {
std::cout << "type\n";
}
};
int main() {
Foo<float> f;
f.function1(1, 1);
f.function1(1.0f,1.0f);
Foo<int> g;
g.function1(1,1);
g.function1(1.0f,1.0f);
g.function1(1.0,1.0); // warning!
}
Output:
type
type
type
float
type
You'll need C++11 mode, to allow the default template parameter in a function template. And also to get enable_if and is_same, although you could get enable_if from Boost instead.
The "warning!" is because with your original code g.function1(1.0,1.0); was ambiguous. Now the the non-template overload is preferred. You can make it ambiguous again by doing
template <typename T = Type>
void function1(float a, Type b, typename std::enable_if<true>::type *c = 0) {
std::cout << "type\n";
}