So i made a template struct cause i want to be able to decide what type i give to my val
. But when creating a function i don't know how to do it.
Here's what i'm doing:
In my .hpp
template<typename T>
struct Integer
{
T val;
void setUint(const T &input);
};
Now i can set what variable i want in the val and what i want in the function.
But now in my cpp i don't know how to invoke the function.
void Integer<T>::setUint(const T &input)
{
val = input;
}
Error: identifier "T" is undefined.
CodePudding user response:
Syntax is
template <typename T>
void Integer<T>::setUint(const T &input)
{
val = input;
}
CodePudding user response:
A template function is a way to operate with generic types (you may consider the type as an argument). your template parameters T
allows to pass different types to a function whern you invoke it. Please, have a look at the simple example.
#include <iostream>
#include <typeinfo>
// you may put it all in a hpp and thus include the hpp file in the CPP
template<typename T>
struct Integer
{
T val;
void setUint(const T &input){
val=input;
std::cout <<"the type is " << typeid(T).name() << " value is "<< val << std::endl;
}
};
// or look at Jarod42's implementation details.
/*
template<typename T>
void Integer<T>::setUint(const T &input){
val=input;
std::cout <<"the type is " << typeid(T).name() << " value is "<< val << std::endl;
}*/
// and here you have your cpp calling you template function with different types
int main()
{
Integer<double> value;
value.setUint(1500000);
Integer<int> value2;
value2.setUint(5);
}
CodePudding user response:
Also for templates, check if T actually matches your expectations. Your template will not make sense for types that are not Integers. Example on how to add these constraints here : https://godbolt.org/z/YsneKe7vj (both C 17 SFINAE, and C 20 concept)
#include <type_traits>
#include <string>
//-----------------------------------------------------------------------------------------------------------
// for C 17 setup a constexpr that will evaluate (at compile time, that's the constexpr bit)
// if a given type is an integer type
template<typename type_t>
constexpr bool is_integer_type_v = std::is_integral_v<type_t> && !std::is_same_v<type_t,bool>;
// create a template that can optionally be enabled. This is an example of a technique called SFINAE
template<typename type_t, typename enable = void>
struct Integer;
// for C define a specialization that will succesfully be enabled of integer types only
template<typename type_t>
struct Integer<type_t,std::enable_if_t<is_integer_type_v<type_t>>>
{
void Set(const type_t v)
{
value = v;
}
type_t value;
};
//-----------------------------------------------------------------------------------------------------------
// for C 20 use concepts
template<typename type_t>
concept is_integer = std::is_integral_v<type_t> && !std::is_same_v<type_t, bool>;
// note is_integer now replaces typename, and it can only accept types
// that satisfy the concept
template<is_integer integer_t>
struct IntegerCpp20
{
void Set(const integer_t v)
{
value = v;
}
integer_t value;
};
//-----------------------------------------------------------------------------------------------------------
int main()
{
//Integer<std::string> value; // will not compile;
Integer<int> value;
value.Set(2);
//IntegerCpp20<std::string> value; // will not compile;
IntegerCpp20<int> value20;
value20.Set(20);
return 0;
}