Elegant function definition in C++ - c++

I have the following functions:
void func1(int8_t input);
void func1(int16_t input);
void func1(int32_t input);
void func1(float input);
The implementation of the four functions is the same, except for some internal value that are in accordance with the input type (int8_t, int16_t, int32_t or float).
Currently I am creating the other three functions by copy-paste but this is quite tedious.
Is there any way so that I only write 1 function (for example, func1(int8_t input);) and that at building time, the other three functions are created automatically?
Or in which this could work with no need of the other three functions? Any other solution is well appreciated.

Usage of template function is the solution for this problem:
template <typename T>
void func1(const T value)
{
// Do some stuff
}
If you need to use special internal value, which depends on input type, you can use auxiliary type traits like this:
template <typename T>
struct SomeTrait
{
static const int value = 10;
};
template <>
struct SomeTrait<float>
{
static const int value = 20;
};
template <typename T>
void func1(const T value)
{
std::cout << SomeTrait<T>::value << std::endl;
// Do some stuff
}

This is clearly needing a template function. This will require C++11
#include <type_traits>
template <typename T
// This constrains the template function instantiation to only
// integral and floating types
typename = typename std::enable_if<std::is_integral<T>::value
||
std::is_floating_point<T>::value>::type>
void func1(T input)
{
......
T tmp; // Use the same data type inside function
}
If you want to keep it simple and w/o C++11, then just do
template <typename T>
void func1(T input)
{
......
T tmp; // Use the same data type inside function
}
The disadvantage is that you cannot constrain the instantiation of this function template only to integral and floating types. You can use boost::enable_if and other type traits instead of 'std::enable_if' and std:: type_traits in this case though.

You can define it as a template function:
template<typename T> void func1(T input) {
// ...
}
Then call it like this:
float f = 1.234;
func1<float>(f);
int32_t i32 = 45678;
func1<int32_t>(i32);

You can use templates if the implementation of the functions are equal:
template <typename T>
void func1(const T value)
{
// Do some stuff
}
If the implementation is different for some input type you can specify this specialization, e.g.
void func1(const complex value)
{
// Do some stuff related to complex values
}

The best way to do this is using template function.
template <typename T>
void your_function(const T input){
// do something
}
in the other hand, you can specify your template function
template <>
void your_function(const float input){
// do some specific things
}

Related

C++ Single function pointer for all template instances

Is there a concise way to point to all instances of a templated function without using macros?
I have several templated functions that I want to test across a variety of types:
template<typename T>
void function1() {
return;
}
template<typename T>
void function2() {
return;
}
template<typename T>
void function3() {
return;
}
I can do this with a macro:
#define TEST_ACROSS_TYPES(fn) \
fn<int>(); \
fn<bool>(); \
fn<char>(); \
fn<double>(); \
TEST_ACROSS_TYPES(function1);
TEST_ACROSS_TYPES(function2);
But, (1) Macros are ugly and hard for others to follow, and (2) I'm using CATCH, which doesn't play nice when using macros to set up test cases.
Is there a way to do something like this:
void testAcrossTypes(SomeType f) {
f<int> ();
f<bool> ();
f<char> ();
f<double> ();
}
which seems much cleaner, except for the problem of defining SomeType. This question (How to define typedef of function pointer which has template arguments) explains how to define a pointer to a templated function; but, requires that the template arguments be specified.
For clarification: Imagine function1, function2, and function3 each test a different templated function. Each function needs to be tested for int, byte, char, double, etc. I want to avoid having to explicitly set up many (i.e. num_functions * num_types) tests for each function. Instead, I want to have a single method that points to the test function (function1, function2, etc.) and runs it for each template type, thus consolidating
function1<int>();
function1<byte>();
function1<char>();
function1<double();
...
function2<int>();
function2<byte>();
function2<char>();
function2<double();
...
function3<int>();
function3<byte>();
function3<char>();
function3<double();
...
into just one call per test function
testAcrossTypes(function1);
testAcrossTypes(function2);
testAcrossTypes(function3);
What you are trying to accomplish with
void testAcrossTypes(SomeType f) {
f<int> ();
f<bool> ();
f<char> ();
f<double> ();
}
would be possible if SomeType could be a template template argument. However, the standard does not allow function templates as template template argument.
From the C++11 Standard:
14.3.3 Template template arguments
1 A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.
Your best option is to use functors instead of functions. Example:
template<typename T>
struct function1
{
void operator()() {
return;
}
};
template<typename T>
struct function2
{
void operator()() {
return;
}
};
template < template <typename> class F>
void testAcrossTypes() {
F<int>()();
F<bool>()();
F<char>()();
F<double>()();
}
int main()
{
testAcrossTypes<function1>();
testAcrossTypes<function2>();
}
You can accomplish it by means of a type-erased functor, like the one in the following example:
#include<vector>
template<typename T>
void function1() { }
template<typename T>
void function2() { }
template<typename T>
void function3() { }
struct Test {
template<typename T>
static void proto() {
function1<T>();
function2<T>();
function3<T>();
}
void operator()() {
for(auto &f: vec) f();
}
template<typename... T>
static Test create() {
Test test;
int arr[] = { (test.vec.emplace_back(&proto<T>), 0)... };
(void)arr;
return test;
}
using func = void(*)(void);
std::vector<func> vec;
};
void testAcrossTypes(Test test) {
test();
}
int main() {
testAcrossTypes(Test::create<int, bool, char, double>());
}
It's easy to modify in both cases:
New functions require to be added to the proto static member method and that's all
Adding a new type is a matter of using it when call create, as shown in the above example
The functor will keep in charge of creating the N*M calls to be executed.
Moreover, you don't need to move your functions in a bunch of structs to be able to use them.

How to write template specialization for only SOME of the parameters needed to implement the template

I have a struct called Vector2 which has a template parameter of T.
(vector2.h)
template <typename T>
struct Vector2
{
T Values[2];
// ..... methods .....
};
I have a method called abs() which is a wrapper to the std::abs() function for most types.
(mymath.h)
template <typename T>
static T abs(const T value)
{
return std::abs<T>(value);
}
If I try and pass the vector2 struct to abs() it won't work because the template specialization used in std doesn't include a method for it... obviously, I created it :)
I want to create one.
How can I create a template specialization for a method that takes a struct that requires it's own template parameter?
This was my best guess, but it isn't valid syntax. Is it even possible?
(mymath.cpp)
template <typename T>
static Vector2<T> abs<Vector2<T>>(const Vector2<T>& vector)
{
return vector.abs(); //this exists
}
Function template can only be fully specialized. You can't partially specialize a function template. However, you can specialize class templates and have a static member in such a class:
template <typename T>
struct abs_helper {
static T abs(T const value) { return std::abs(value); }
};
template <typename T>
struct abs_helper<Vector2<T>> {
static Vector2<T> abs(Common::Vector2<T> const& matrix) { return matrix.abs(); }
};
template <typename T>
auto abs(T&& value)
-> decltype(abs_helper<std::remove_const_t<std::remove_reference_t<T>>>::abs(std::forward<T>(value))) {
return abs_helper<std::remove_const_t<std::remove_reference_t<T>>>::abs(std::forward<T>(value));
}
The forwarding is a bit complicate given that your code uses different approaches to pass arguments for the two different functions: the code tries to mimick this forward (I haven't tried to compile it).
Just to explain a bit what's going on:
The struct abs_helper is a class template which can be partially specialized and is partially specialized for Vector2<T>. The specialization is required to have a static member called abs() taking a suitable argument and returning the desired result.
The function template abs() just forwards to abs_helper<...>::abs(...). Since it forwards its argument it uses prefect forwarding. There are to complications with this forwarding, though:
The template argument deduced for abs() may contain a reference and/or a const which need to be removed before passing it on to the specialized abs_helper (otherwise it would require multiple specialization). Thus, any reference is removed followed by removing any const using the C++14 type traits using alias (std::remove_reference_t<T> and std::remove_const<T>).
The return type seems to differ. To deal with that the code uses C++11 return-type specification combined with determining the type using decltype() based on the actual call of the function.
Not being a c++11 guy, my answer looks a bit different and less scientific. You be the judge if this is what you need. I theorized that your Vector2 version of abs would return the length of the vector. As such, the return value of your Vector2::abs would not be T but double (or float or long) depending on what you need, independent of T for your input arguments. Here is my complete test code for that case...
#include "stdafx.h"
#include <iostream>
#include <cmath>
namespace Common
{
template <typename T>
struct Vector2
{
T Values[2];
// ..... methods .....
double abs() const
{
return std::sqrt(Values[0] * Values[0] + Values[1] * Values[1]);
}
};
}
template <typename T>
static T abs(const T value)
{
return std::abs(value);
}
template <typename T>
static double abs(const Common::Vector2<T>& matrix)
{
return matrix.abs();
}
int _tmain(int argc, _TCHAR* argv[])
{
Common::Vector2<float> v1;
v1.Values[0] = 1.0F;
v1.Values[1] = 1.0F;
std::cout << "Result = " << abs(v1) << std::endl;
return 0;
}

Template specialization for all wide character types

i want to improve my knowledge in c++ templates at the moment and i came across a problem. Is it possible to write a template function which accepts all wide character types like std::wstring, wchar_t, wchar_t* and so on? Here is an example to show what i mean:
template <typename T> Function(T1 var)
{
// Do something with std::stringstream and the passed var;
}
The problem with the function above is that it doesnt work with wchar_t or std::wstring for example. You need to use std::wstringstream instead. I could specialize now like:
template <> Function(wchar_t var)
{
// Do something with std::wstringstream and the passed var;
}
Now i would have to write the same function for each wide string type, but is it possible to specialize once and cover all wide string types?
Thx in advance!
Use traits technique. Define some is_wide_char_type class template. Like this:
template <T>
struct is_wide_char_type { static const bool VALUE = false; };
template <>
struct is_wide_char_type<wchar_t> { static const bool VALUE = TRUE; };
... for others types the same.
Then specialize your function for two versions, you need to define class template because function template cannot be partially specialized:
template <typename T, boo isWideChar> class FunctionImpl;
template <typename T> struct FunctionImpl<T, false> {
static void doIt() {
// code for not wide char types
}
};
template <typename T> struct FunctionImpl<T, true> {
static void doIt() {
// code for wide char types
}
};
template <typename T> Function(T1 var)
{
FunctionImpl<T, is_wide_char_type<T>::VALUE>::doIt();
}
OR consider to make it even easier and enclose in traits is_wide_char_type<T> not the just tag information of kind of T but also about which stringstream to use and whatever you like.

how to carry out few different set of instruction for string datatype in a template?

I have a template member function in a class that is called for all bool, double, int and string. I want to carry out few instructions that are common to all the above mentioned data types. But for String last few lines of code is different. So can any one suggest me a better way to carry out this in a same template function.
template< class T>
xyz (t* a)
{
//few lines are common for all types for data
//last 3 lines of code is different for Strings
}
The solution, as often, is to factorize the common behavior and provide a mean to specialize some parts of the algorithm (see the Template Method pattern).
Here, you can do this quite easily by moving the last lines of your function in a function of its own, which can be specialized for certain data types. Remember that when it comes to functions, overloading should be preferred to template specialization.
template <class T>
void xyz(T * a)
{
//few lines are common for all types for data
xyz_finish(a);
}
template <class T>
void xyz_finish(T * a)
{
// default case (can be empty)
}
void xyz_finish(std::string * s)
{
// string case
}
Of course, your function should have a more descriptive name than the one I used...
You can also do the symmetrical operation: move the common behavior in a function, and overloads the "top-level" function:
template <class T>
void xyz(T * a)
{
common_behavior(a);
}
void xyz(std::string * s)
{
common_behavior(s);
// code specific to strings
}
template <class T>
void common_behavior(T * a)
{
//few lines that are common for all types for data
}
If you do not want or cannot create other functions, you can test the type of the parameter:
template <class T>
void xyz(T * a)
{
// common code
if (is_same<T, std::string>::value)
{
//code for strings
}
}
is_same is a class template containing a value which is true if its two parameters are the same type, available in TR1, Boost and C++0x. This solution will work only if the code in the if clause is valid for every data types you instantiate the template with. For example, if you use a member function of string in the if block, compilation will fail when instantiating the function with the other data types, since you cannot invoke a method on a primitive type.
You can move last 3 lines into some function, and use C++ function overloading, i.e. one for bool, second for int etc, i think.
struct Foo {
template <typename T>
voud foo (T *) {
foo ();
}
void foo (string *) {
foo ();
bar ();
}
private:
void foo () {
}
};
Or
struct Foo {
template <typename T>
void foo (T * t) {
do_foo (t);
}
void foo (string * s) {
do_foo (s);
bar (s);
}
private:
template <typename T>
void do_foo (T *) {
}
};
You could explicitly specialise Foo::foo outside the class.
tempalte <> void Foo :: foo (string *) {}
This seems like it could be put to devious use, though...
You only need to specialise your template for string, as follows:
template<> xyz(string* a) { /* code here, including modified lines */ }
EDIT: Apparently, I did not notice the "member function" bit of it. The solution would be to add an extra indirection, a function that you specialise for string and call at the end of your current function.

Switch passed type from template

Is it possible in C++ to check the type passed into a template function? For example:
template <typename T>
void Foo()
{
if (typeof(SomeClass) == T)
...;
else if (typeof(SomeClass2) == T)
...;
}
Yes, it is...but it probably won't work the way you expect.
template < typename T >
void foo()
{
if (is_same<T, SomeClass>::value) ...;
else if (is_same<T, SomeClass2>::value) ...;
}
You can get is_same from std:: or boost:: depending on your desire/compiler. The former is only in C++0x.
The problem comes with what is in .... If you expect to be able to make some function call specific to those types within foo, you are sadly mistaken. A compiler error will result even though that section of code is never run when you pass in something that doesn't obey that expected interface.
To solve THAT problem you need to do something a bit different. I'd recommend tag dispatching:
struct v1_tag {};
struct v2_tag {};
template < typename T > struct someclass_version_tag;
template < > struct someclass_version_tag<SomeClass> { typedef v1_tag type; };
template < > struct someclass_version_tag<SomeClass2> { typedef v2_tag type; };
void foo(v1_tag) { ... }
void foo(v2_tag) { ... }
template < typename T > void foo()
{
typedef typename someclass_version_tag<T>::type tag;
foo(tag());
}
Note that you will not be suffering any runtime-polymorphism overhead here and with optimizations turned on it should result in the same or even smaller code size AND speed (though you shouldn't be worrying about that anyway until you've run a profiler).
If you want to do something specific based on the type, specialize the template:
template <typename T>
void Foo() { }
template <>
void Foo<SomeClass>() { }
template <>
void Foo<SomeClass2>() { }
// etc.
(You don't actually want to specialize the function template, though; this is for exposition only. You'll either want to overload the template if you can, or delegate to a specialized class template. For more on why and how to avoid specializing function templates, read Herb Sutter's Why Not Specialize Function Templates?)
No, however you can use partial specialization :
template<typename T>
struct Bar { static void foo(); };
template<typename T>
template<> inline void Bar<T>::foo() {
//generic
}
template<> inline void Bar<int>::foo() {
//stuff for int
}
template<> inline void Bar<QString>::foo() {
//QString
}
Edit Yes with type traits, however it's not really needed.
Edit 2 type_traits example.
#include <type_traits>
template<typename T> void foo() {
using std::is_same;
if (is_same<T, T2>::value || is_same<T, T1>::value) {
/* stuff */
}
}
Yes. You will have to use type traits. For example:
#include <boost/type_traits/is_same.hpp>
template <typename T>
void Foo ()
{
if ((boost::is_same<T, SomeClass>::value))
...;
else if ((boost::is_same<T, SomeClass2>::value))
...;
}
Depending on what you are trying to achieve, using template specialization might be much better choice.
Also, you can use enable_if/disable_if to conditionally enable/disable certain functions/methods. Combining this with type traits will allow, for example, using one function for one set of types and another function for another set of types.