#include <iostream>
using namespace std;
template<typename T>
void fun(const T & val)
{
cout << " T " << endl;
}
template<>
void fun<int>(const int & val)
{
cout << " specialization same code " << val << endl;
}
template<>
void fun<double>(const double& val)
{
cout << " specialization same code " << val << endl;
}
int main()
{
fun( 1 );
fun( 1.0 );
fun( 'c' );
return 0;
}
Question> Is there a way that I can reuse the function specialization code?
For example, assume both 'int and 'double' specialization has the exactly same implementation code. Is there a method I can prevent the code duplication?
http://codepad.org/awGYWiWv
Thank you
As suggested by #0x499602D2 in the comments, create another function and make sure it gets called only for int or double.
template<typename T>
void bar(const T & val)
{
// Make sure this gets called only for int or double.
static_assert(std::is_same<T, int>::value || std::is_same<T, double>::value);
// Do useful stuff with val.
}
template<>
void fun<int>(const int & val)
{
bar(val);
}
template<>
void fun<double>(const double& val)
{
bar(val);
}
To reuse the same code for multiple types of the same kind, you could use std::enable_if (or boost::enable_if if you are not using C++11) with type traits (a nice example is here).
e.g.:
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
fun(const T& val)
{
cout << " floating point specialisation " << val << endl;
}
(function specialisations of this kind work only in C++11, but you can use a struct or class for the same purpose in older C++ versions)
something like this should give you the level of re-use you want:
#include <iostream>
#include <type_traits>
using namespace std;
// will only compile if T is an arithmetic type
template<typename T,
typename std::enable_if<
std::is_arithmetic<T>::value>::type* = nullptr>
void fun(T val)
{
cout << "the square is " << val * val << endl;
}
int main()
{
int x = 10;
double y = 10;
fun(x);
fun(y);
return 0;
}
Related
I wish to send an integer to a function, that integer might be 8/16 bits depending on conditions. Can I declare one function to receive either int8/in16 as argument, depending on what the caller sends? Or, do I have to declare two functions one for each type (what I am doing at present)?
void func(uint8_t/uint16_t value)
or
void func(uint8_t value)
void func(uint16_t value)
This can be done by using function template and SFINAE as shown below:
#include <cstdint>
#include <iostream>
template <typename T> std::enable_if_t<std::is_same_v<T, uint8_t>> func(const T& t)
{
std::cout << "uint8 version called" <<std::endl;
}
template <typename T> std::enable_if_t<std::is_same_v<T, uint16_t>> func(const T& t)
{
std::cout << "uint16 version called" <<std::endl;
}
int main()
{
uint8_t x = 4;
func(x); //calls uint8 version
uint16_t y = 4;
func(y); //calls uint16_t version
}
#Jason Liam is onto it, but if you want to different functions, standard overloading is the answer. If you want to use a single function for those two types, combine Jason's functions:
#include <cstdint>
#include <iostream>
#include <typeinfo>
template <typename T> void func(const T& t) requires
std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t>
{
std::cout << "called with type " << typeid(T).name() <<std::endl;
}
int main()
{
uint8_t x = 4;
func(x); //calls uint8_t version
uint16_t y = 4;
func(y); //calls uint16_t version
int z = 6;
// func(z); compiler error, z is not right type
}
Test in compiler explorer
With C++20, we can use requires clause instead of SFINAE to do the same:
#include <cstdint>
#include <iostream>
template <typename T> void func(const T& t) requires std::is_same_v<T, uint8_t>
{
std::cout << "uint8 version called" <<std::endl;
}
template <typename T> void func(const T& t) requires std::is_same_v<T, uint16_t>
{
std::cout << "uint16 version called" <<std::endl;
}
int main()
{
uint8_t x = 4;
func(x); //calls uint8 version
uint16_t y = 4;
func(y); //calls uint16_t version
}
void func(uint8_t/uint16_t value)
The only way to do this exactly (without a function template instantiated as two functions) is with std::variant (or some other discriminated union).
void func(std::variant<uint8_t, uint16_t> value)
{
}
is precisely what you requested.
When you start implementing the body, you'll find it's often simpler to delegate to a templated visitor, and then you're back to the existing answers (but with a relatively expensive runtime decision about the type instead of a static one).
Demonstration in compiler explorer
void func(std::variant<uint8_t, uint16_t> value)
{
std::cout << "called with type index " << value.index() << '\n';
// templated visitor
std::visit(
[](auto && val)
{
std::cout << "called with type " << typeid(val).name()
<< ", value " << val << '\n';
},
value
);
// alternatively, test each type by hand
if (std::holds_alternative<uint8_t>(value))
{
std::cout << "got uint8_t alternative " << std::get<uint8_t>(value)
<< '\n';
}
else if (std::holds_alternative<uint16_t>(value))
{
std::cout << "got uint16_t alternative " << std::get<uint16_t>(value)
<< '\n';
}
}
I wish to send an integer to a function, that integer might be 8/16 bits depending on conditions. Can I declare one function to receive either int8/in16 as argument, depending on what the caller sends? Or, do I have to declare two functions one for each type (what I am doing at present)?
void func(uint8_t/uint16_t value)
or
void func(uint8_t value)
void func(uint16_t value)
This can be done by using function template and SFINAE as shown below:
#include <cstdint>
#include <iostream>
template <typename T> std::enable_if_t<std::is_same_v<T, uint8_t>> func(const T& t)
{
std::cout << "uint8 version called" <<std::endl;
}
template <typename T> std::enable_if_t<std::is_same_v<T, uint16_t>> func(const T& t)
{
std::cout << "uint16 version called" <<std::endl;
}
int main()
{
uint8_t x = 4;
func(x); //calls uint8 version
uint16_t y = 4;
func(y); //calls uint16_t version
}
#Jason Liam is onto it, but if you want to different functions, standard overloading is the answer. If you want to use a single function for those two types, combine Jason's functions:
#include <cstdint>
#include <iostream>
#include <typeinfo>
template <typename T> void func(const T& t) requires
std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t>
{
std::cout << "called with type " << typeid(T).name() <<std::endl;
}
int main()
{
uint8_t x = 4;
func(x); //calls uint8_t version
uint16_t y = 4;
func(y); //calls uint16_t version
int z = 6;
// func(z); compiler error, z is not right type
}
Test in compiler explorer
With C++20, we can use requires clause instead of SFINAE to do the same:
#include <cstdint>
#include <iostream>
template <typename T> void func(const T& t) requires std::is_same_v<T, uint8_t>
{
std::cout << "uint8 version called" <<std::endl;
}
template <typename T> void func(const T& t) requires std::is_same_v<T, uint16_t>
{
std::cout << "uint16 version called" <<std::endl;
}
int main()
{
uint8_t x = 4;
func(x); //calls uint8 version
uint16_t y = 4;
func(y); //calls uint16_t version
}
void func(uint8_t/uint16_t value)
The only way to do this exactly (without a function template instantiated as two functions) is with std::variant (or some other discriminated union).
void func(std::variant<uint8_t, uint16_t> value)
{
}
is precisely what you requested.
When you start implementing the body, you'll find it's often simpler to delegate to a templated visitor, and then you're back to the existing answers (but with a relatively expensive runtime decision about the type instead of a static one).
Demonstration in compiler explorer
void func(std::variant<uint8_t, uint16_t> value)
{
std::cout << "called with type index " << value.index() << '\n';
// templated visitor
std::visit(
[](auto && val)
{
std::cout << "called with type " << typeid(val).name()
<< ", value " << val << '\n';
},
value
);
// alternatively, test each type by hand
if (std::holds_alternative<uint8_t>(value))
{
std::cout << "got uint8_t alternative " << std::get<uint8_t>(value)
<< '\n';
}
else if (std::holds_alternative<uint16_t>(value))
{
std::cout << "got uint16_t alternative " << std::get<uint16_t>(value)
<< '\n';
}
}
I want to write a function which distinguish between arrays and pointers. This is needed in order to figure size of literal strings. I tried:
template<typename Ty>
void f(const Ty* rhs) {
std::cout << __FUNCTION__ << rhs << std::endl;
}
template<typename Ty, size_t Dm>
void f(const Ty(&rhs)[Dm]) {
std::cout << __FUNCTION__ << rhs << std::endl;
}
int main(int, char*[]) {
const char arr0[] = "test2";
const char* ptr = "test3";
const char arr6[6] = "test4";
f("test1");
f(arr0);
f(ptr);
f(arr6);
return 0;
}
But the compiler (VS2013) tells me that the call is ambiguous. Any hints?
Thanks in advance.
Unfortunately, the call are ambiguous.
As workaround, you may add an extra layer:
template<typename Ty>
void f_pointer(const Ty* rhs) {
std::cout << __FUNCTION__ << rhs << std::endl;
}
template<typename Ty, size_t Dm>
void f_array(const Ty(&rhs)[Dm]) {
std::cout << __FUNCTION__ << rhs << std::endl;
}
template<typename T>
std::enable_if_t<std::is_array<T>::value>
f(const T&t)
{
f_array(t);
}
template<typename T>
std::enable_if_t<!std::is_array<T>::value>
f(const T&t)
{
f_pointer(t);
}
Live Demo
An alternative to Jarod42's answer (which works) is to use class template specialization:
#include <iostream>
#include <type_traits>
template <typename T, bool is_array>
struct f_helper {
static void print_type (T& arg) {
std::cout << arg << " is an array\n";
}
};
template <typename T>
struct f_helper<T, false> {
static void print_type (T arg) {
std::cout << arg << " is not an array\n";
}
};
template <typename T>
void f (T& arg) {
f_helper<T, std::is_array<T>::value>::print_type (arg);
}
int main(int, char*[]) {
const char arr0[] = "test2";
const char* ptr = "test3";
const char arr6[6] = "test4";
f("test1");
f(arr0);
f(ptr);
f(arr6);
return 0;
}
Live demo
Change the reference to a pointer in the second overload of the function template:
template<typename T, size_t S> void f(T(&)[S]){
cout << "array with size " << S << "\n";
}
template <typename T> void f(T*&) {
cout << "pointer \n";
}
Live Demo
I don't believe it's possible to do what you're trying the way you're trying. The following statements evaluate to the same thing:
int* var
int var[]
It's all a matter of syntax sugar. Moreover, adding a size to the array on the function header has only the benefit of warning the user of the expected array size. Therefore the two are also equivalent (as far as the compiler is concerned):
void f(int* v)
void f(int v[8])
I want to use SFINAE to enable a particular template if the user passes a function pointer as a parameter.
I have googled around but found nothing - I also tried looking at the <type_traits> documentation but couldn't find anything that resembled a is_function_ptr<T>.
By function pointer, I mean global function pointers, like TReturn(*)(TArgs...).
Below is a type trait determining if something is a function pointer and a couple of test cases. Note, that to test if something is a function pointer, you need to test if std::is_pointer<P>::value is true and if std::is_function<T>::value is true where T is P with the pointer removed. The code below just does that:
#include <type_traits>
#include <iostream>
#include <utility>
template <typename Fun>
struct is_fun_ptr
: std::integral_constant<bool, std::is_pointer<Fun>::value
&& std::is_function<
typename std::remove_pointer<Fun>::type
>::value>
{
};
template <typename Fun>
typename std::enable_if<is_fun_ptr<Fun>::value>::type
test(Fun) {
std::cout << "is a function pointer\n";
}
template <typename Fun>
typename std::enable_if<!is_fun_ptr<Fun>::value>::type
test(Fun) {
std::cout << "is not a function pointer\n";
}
void f0() {}
void f1(int) {}
void f2(int, double) {}
struct s0 { void operator()() {} };
struct s1 { void operator()(int) {} };
struct s2 { void operator()(int, double) {} };
int main()
{
int v0(0);
int* p0(&v0);
void (*p1)() = &f0;
void (**p2)() = &p1;
std::cout << "v0="; test(v0);
std::cout << "p0="; test(p0);
std::cout << "p1="; test(p1);
std::cout << "p2="; test(p2);
std::cout << "f0="; test(&f0);
std::cout << "f1="; test(&f1);
std::cout << "f2="; test(&f2);
std::cout << "s0="; test(s0());
std::cout << "s1="; test(s1());
std::cout << "s2="; test(s2());
std::cout << "l0="; test([](){});
std::cout << "l1="; test([](int){});
std::cout << "l2="; test([](int, double){});
}
No SFINAE is needed to accept a function pointer or a member function pointer. To distinguish function objects from non-callable stuff SFINAE is needed, there's probably no way around this.
#include <utility>
#include <iostream>
template <typename Ret, typename... Parm>
void moo (Ret (*fp)(Parm...))
{
std::cout << "funptr" << std::endl;
}
template <typename Ret, typename Owner, typename... Parm>
void moo (Ret (Owner::*fp1)(Parm...))
{
std::cout << "memfunptr" << std::endl;
}
template <typename Funobj, typename... Parm,
typename Ret =
decltype((std::declval<Funobj>())
(std::forward(std::declval<Parm>())...))>
void moo (Funobj functor)
{
std::cout << "funobj" << std::endl;
}
void x1() {}
struct X2 { void x2() {} };
struct X3 { void operator()(){} };
int main()
{
moo(x1);
moo(&X2::x2);
moo(X3());
}
Is it possible to build only some part of the code given the type of the template in C++ ?
It would be something lake that :
#include <iostream>
using namespace std;
template<typename T>
void printType(T param)
{
#if T == char*
cout << "char*" << endl;
#elif T == int
cout << "int" << endl;
#else
cout << "???" << endl;
#endif
}
int main()
{
printType("Hello world!");
printType(1);
return 0;
}
Type traits:
#include <iostream>
#include <type_traits> // C++0x
//#include <tr1/type_traits> // C++03, use std::tr1
template<typename T>
void printType(T param)
{
if(std::is_same<T,char*>::value)
std::cout << "char*" << endl;
else if(std::is_same<T,int>::value)
std::cout << "int" << endl;
else
std::cout << "???" << endl;
}
Or even better yet, just overload the function:
template<class T>
void printType(T partam){
std::cout << "???" << endl;
}
void printType(char* partam){
std::cout << "char*" << endl;
}
void printType(int partam){
std::cout << "int" << endl;
}
Partial ordering will take care that the correct function is called. Also, overloading is preferred to template specialization in the general case, see this and this artice for why. Might not apply for you if you totally have to print the type, as implicit conversions are considered for overloaded functions.
Since C++17 there is a way to do exactly this with if-constexpr. The following compiles since clang-3.9.1, gcc-7.1.0, and recent MSVC compiler 19.11.25506 handles well too with an option /std:c++17.
#include <iostream>
#include <type_traits>
template<typename T>
void printType(T)
{
if constexpr (std::is_same_v<T, const char*>)
std::cout << "const char*" << std::endl;
else if constexpr (std::is_same_v<T, int>)
std::cout << "int" << std::endl;
else
std::cout << "???" << std::endl;
}
int main()
{
printType("Hello world!");
printType(1);
printType(1.1);
return 0;
}
Output:
const char*
int
???
Use template specialization:
template<typename T>
void printType(T param)
{
// code for the general case - or omit the definition to allow only the specialized types
}
template<>
void printType<char*>(char* param)
{
// code for char*
}
template<>
void printType<int>(int param)
{
// code for int
}
// ...
You can use a specialization. The preprocessor runs before all templates and cannot interact with them.
template<typename T> void printType(T t) {
std::cout << typeid(T).name(); // fallback
}
template<> void printType<char*>(char* ptr) {
std::cout << "char*";
}
template<> void printType<int>(int val) {
std::cout << "int";
}
You use template specification to specify versions of your function to work differently based on its type. For example, you can make a generic version of a function that would work with most types, and make a specific version for e.g. int that will be faster. You'd do it this way:
template <class T>
void printType(T param)
{
cout<<"Generic version"<<endl;
}
template <>
void printType<int>(int param)
{
cout<<"Int version"<<endl;
}
template <>
void printType<char>(char param)
{
cout<<"Char version"<<endl;
}
//Rince and repeat.