Template Specilization with multiple template parameters in one function - c++

I want template specilization with two parameters in one function. Here is a sample of code.
#include <iostream>
#include <string>
template <typename T>
class Printer
{
public:
T value;
Printer(T value)
{
this->value = value;
}
void print();
};
template <typename T> void Printer<T>::print()
{
std::cout << value << "\n";
}
template <> void Printer<std::string>::print()
{
std::cout << "\"" << value <<"\"\n";
}
template <> void Printer<const char *>::print()
{
std::cout << "\"" << value <<"\"\n";
}
int main()
{
Printer<int> print1(2);
Printer<std::string> print2("Printing string");
Printer<const char *> print3("Printing char*");
print1.print();
print2.print();
print3.print();
}
Is there a way I can make the template speciazation for std::string and const char * in one function. I want this because they are doing the same thing.

You can use traits to add indirection on the specific behavior, based on type.
#include <iostream>
#include <string>
template <typename T>
class Printer
{
public:
T value;
Printer(T value)
{
this->value = value;
}
void print();
};
template<typename T>
struct PrinterTypeTraits {
static constexpr char* prefix = "";
static constexpr char* postfix = "";
};
template<>
struct PrinterTypeTraits<std::string> {
static constexpr char prefix = '\"';
static constexpr char postfix = '\"';
};
template<>
struct PrinterTypeTraits<const char*> : PrinterTypeTraits<std::string> {};
template <typename T> void Printer<T>::print()
{
using Traits = PrinterTypeTraits<T>;
std::cout << Traits::prefix << value << Traits::postfix << '\n';
}
int main()
{
Printer<int> print1(2);
Printer<std::string> print2("Printing string");
Printer<const char *> print3("Printing char*");
print1.print();
print2.print();
print3.print();
return 0;
}

Related

Templated snprintf

I need to convert some numbers (integers and doubles) into std::strings, and for performance reasons cannot use stringstream (we found it to be very slow when used concurrently)
It would be nice to be able to do something like
template<typename T>
static const std::string numberToString(T number)
{
char res[25];
// next line is a bit pseduo-y
snprintf(res, sizeof(res), "%T", number);
return string(res);
}
But I'm not really sure how is the best way to achieve this?
Here's one idea. Use:
template<typename T>
static const std::string numberToString(T number)
{
char res[25];
snprintf(res, sizeof(res), getPrintfFormat<T>(), number);
return res;
}
Sample program:
#include <iostream>
#include <cstdio>
#include <string>
template <typename T> struct PrintfFormat;
template <> struct PrintfFormat<int>
{
static char const* get() { return "%d"; }
};
template <> struct PrintfFormat<float>
{
static char const* get() { return "%f"; }
};
template <> struct PrintfFormat<double>
{
static char const* get() { return "%f"; }
};
template <typename T>
char const* getPrintfFormat()
{
return PrintfFormat<T>::get();
}
template<typename T>
static const std::string numberToString(T number)
{
char res[25];
snprintf(res, sizeof(res), getPrintfFormat<T>(), number);
return res;
}
int main()
{
std::cout << numberToString(10) << std::endl;
std::cout << numberToString(10.2f) << std::endl;
std::cout << numberToString(23.456) << std::endl;
}
Output:
10
10.200000
23.456000
It also provides a level of type safety. With the posted code, using
std::cout << numberToString('A') << std::endl;
will result in a compile time error.

template SFINAE and enable_if to switch between dynamic and fixed size

I am new to SFINAE. I have a template that I would like to be able to accept classes that the size could be determined simply calling sizeof(x) or in case the value is dynamic it will require x.size().
I am trying to wrap my head around how as smooth as possible this could looks like and I think interface: size_t size(const Item& item) seems to be good enough.
The following is an example that works:
#include <iostream>
#include <cstdio>
#include <type_traits>
template <typename T>
class Fixed {
public:
typedef T Item;
static const bool kFixedSize = true;
static size_t size() {
return sizeof(T);
}
};
template <typename T>
class Dynamic {
public:
typedef T Item;
static const bool kFixedSize = false;
static size_t size(const T& item) {
return item.size();
}
};
template <typename T>
class Serialize {
public:
template <typename = typename std::enable_if<T::kFixedSize> >
size_t size(typename T::Item&) {
return T::size();
}
template <typename = typename std::enable_if<!T::kFixedSize> >
size_t size(const typename T::Item& item) {
return T::size(item);
}
};
int main() {
Serialize< Fixed<int> > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
Serialize< Dynamic<std::string> > dynamic;
std::cout << dynamic.size("string") << std::endl;
return 0;
}
It has an issues though one is: size_t size(typename T::Item&) and the other is size_t size(const typename T::Item& item) else the compiler compliance that I am overloading the template. The second is it seems like too match very tricky code to achieve the goal - is there better ways to do this?
I believe you want something like this
//class hierarchy to set the priority for type matching
struct second_priority
{
};
struct first_priority : public second_priority
{};
template<typename T>
auto size_impl(T const & data, second_priority t) -> int
{
return sizeof(data);
}
template<typename T>
auto size_impl(T const & data , first_priority t) -> decltype(data.size(),int())
{
return data.size();
}
template<typename T>
int size(T const & data )
{
return size_impl(data,first_priority{});
}
I think #Gautam Jha presented a nice solution using SFINAE. You can shorten it a bit by using ellipsis for the 'else' case, so you don't need to use this auxiliary class and it's inheritance:
template<typename T>
auto size_impl(T const & item, int) -> decltype(item.size())
{
return item.size();
}
template<typename T>
auto size_impl(T const & item, ...) -> size_t
{
return sizeof(T);
}
template<typename T>
auto size(T const & item) -> size_t
{
return size_impl(item, 0);
}
It's cool that you're playing around with SFINAE, but usually there are simpler (i.e. to read and to understand) ways to achieve the same, see the solution of POW (which has unfortunately been deleted).
Since all you want to do is call different functions to get the size in Dynamic or Fixed, you can just implement these classes differently and use them in Serialize:
#include <iostream>
#include <cstdio>
#include <type_traits>
template <typename T>
class Fixed {
public:
typedef T Item;
static size_t size(const T&) {
return sizeof(T);
}
};
template <typename T>
class Dynamic {
public:
typedef T Item;
static size_t size(const T& item) {
return item.size();
}
};
template <typename T>
class Serialize {
public:
size_t size(typename T::Item const& x) {
return T::size(x);
}
};
int main() {
Serialize< Fixed<int> > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
Serialize< Dynamic<std::string> > dynamic;
std::cout << dynamic.size( std::string{"string"} ) << std::endl;
return 0;
}
However, I would consider using a type-trait or a free function to do the same. This would be more extensible, because you have to just provide a new trait or an overload for new types, e.g. some container which has only a length method.
#include <iostream>
#include <cstdio>
#include <type_traits>
size_t size(int) {return sizeof(int);}
size_t size(std::string const& s) {return s.size();}
template<typename T>
struct size_trait
{
};
template<>
struct size_trait<int>
{
static size_t size(int) {return sizeof(int);}
};
template<>
struct size_trait<std::string>
{
static size_t size(std::string const& x) {return x.size();}
};
template <typename T>
class Serialize {
public:
size_t size(T const& x) {
return ::size(x);
}
size_t size_(T const& x) {
return size_trait<T>::size(x);
}
};
int main() {
Serialize< int > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
std::cout << fixed.size_(a) << std::endl;
Serialize< std::string > dynamic;
std::cout << dynamic.size( std::string{"string"} ) << std::endl;
std::cout << dynamic.size_( std::string{"string"} ) << std::endl;
return 0;
}

Template Function Specialization

I am doing an exercise on templates and I am now dealing with specializations. I have defined a function T read_val(T& v) that takes input from cin and compiles the T val inside my template<typename T> struct S. I wish to specialize this function to types int, double, char, string but, when I am trying to do it, I'm keep getting errors. Here is what I wrote:
Header.h:
#ifndef Templates_Header_h
#define Templates_Header_h
#include <iostream>
using namespace std;
template<typename T>
struct S
{
private:
T val;
public:
S() : val{} {};
T* get();
T* get() const;
T set();
T operator=(const T&);
T read_val(T& v);
void print_val() const;
};
template<typename T>
void S<T>::print_val() const
{
cout << "Value is: " << val << endl;
}
template<typename T>
T* S<T>::get()
{
T* p = &val;
return p;
}
template<typename T>
T S<T>::set()
{
T newvalue;
cout << "Type new value: ";
cin >> newvalue;
S<T>::val = newvalue;
return S<T>::val;
}
template<typename T>
T S<T>::operator=(const T&)
{
T val1;
val1 = val;
return *this;
}
template<typename T>
T* S<T>::get() const
{
T* p = &val;
return p;
}
template<typename T>
T S<T>::read_val(T &v)
{
cout << "Type Value: ";
cin >> v;
return S<T>::val = v;
}
#endif
Header.cpp
#include <stdio.h>
#include "Header.h"
#include "std_lib_facilities.h"
template <>
struct S <int> // Specialization
{
private:
int val;
public:
S() : val{0} {};
};
template<>
struct S<char> // Specialization
{
private:
char val;
public:
S() : val{'0'} {};
};
template <>
struct S<double> // Specialization
{
private:
double val;
public:
S() : val{0.0} {};
};
template <>
struct S<string> // Specialization
{
private:
string val;
public:
S() : val{""} {};
};
template<>
struct S<vector<int>> // Specialization
{
private:
vector<int> val;
public:
S() : val{0} {};
};
template<> // !! ERROR !!
int read_val(int& v)
{
cout << "Type a value: ";
cin >> v;
return v;
}
Xcode is reporting "No function template matches function template specialization 'read_val'". I was surfing the net reading examples and references but I cannot solve it. Can you help me? I need an example to fix it in mind.
Thanks!
There should be no CPP file for a template header. Your implementation is already in the header file!
Create main.cpp with:
#include "Header.h"
#include <iostream>
int main()
{
S<int> my_S;
int val;
my_S.read_val(val/*by ref*/);
std::cout << "The read value is " << val << std::endl;
return 0;
}
Or something like that, I didn't compile it...
According to your implementation I see that you missed the point of templates. You need to define it only once (no need to rewrite it manually for each type like int, float, etc., the compiler will do it for you).

how to generate code to initialize a std::vector with a custom Zero value if it exists as T::Zero?

BACKGROUND
I have a container class that has a std::vector<T> member that I initialize with the constructor that takes size_t n_items. I would like to initialize that vector with my own Zero() function which returns 0; by default, but if static member T::Zero exists I want to return that instead.
In my first attempt, I use expression SFINAE, but that failed due to ambiguous overload since both the generic version of Zero and the Zero have the same signature with no arguments. So now, I'm trying to convert the code into classes with operator().
I think I need to use std::enable_if somehow, but I'm not sure how to go about coding this.
FAILED ATTEMPT
#include <cassert>
#include <iostream>
#include <vector>
template<typename T>
struct Zero
{
T operator() const { return 0; }
};
template<typename T>
struct Zero
{
auto operator() const ->
decltype( T::Zero )
{
return T::Zero;
}
};
struct Foo
{
char m_c;
static Foo Zero;
Foo() : m_c( 'a' ) { }
Foo( char c ) : m_c( c ) { }
bool operator==( Foo const& rhs ) const { return m_c==rhs.m_c; }
friend std::ostream& operator<<( std::ostream& os, Foo const& rhs )
{
os << (char)(rhs.m_c);
return os;
}
};
Foo Foo::Zero( 'z' );
int
main( int argc, char** argv )
{
std::vector<unsigned> v( 5, Zero<unsigned>() );
std::vector<Foo> w( 3, Zero<Foo>() );
for( auto& x : v )
std::cout << x << "\n";
std::cout << "---------------------------------\n";
for( auto& x : w )
{
assert( x==Foo::Zero );
std::cout << x << "\n";
}
std::cout << "ZERO = " << Foo::Zero << "\n";
return 0;
}
#include <string>
#include <iostream>
#include <vector>
#include <type_traits>
namespace detail
{
template<class T, class = decltype(T::zero)>
std::true_type has_zero_impl(int);
template<class T>
std::false_type has_zero_impl(short);
}
template<class T>
using has_zero = decltype(detail::has_zero_impl<T>(0));
template<class T, class = has_zero<T>>
struct zero
{
constexpr static T get() { return T(); }
};
template<class T>
struct zero<T, std::true_type>
{
constexpr static auto get() -> decltype(T::zero)
{ return T::zero; }
};
Usage example:
template<>
struct zero<std::string>
{
static constexpr const char* get()
{ return "[Empty]"; }
};
struct foo
{
int m;
static constexpr int zero = 42;
};
int main()
{
std::cout << zero<int>::get() << "\n";
std::cout << zero<std::string>::get() << "\n";
std::cout << zero<foo>::get() << "\n";
}
Compact version w/o trait:
template<class T>
struct zero
{
private:
template<class X>
constexpr static decltype(X::zero) zero_impl(int)
{ return X::zero; }
template<class X>
constexpr static X zero_impl(short)
{ return X(); }
public:
constexpr static auto get()
-> decltype(zero_impl<T>(0))
{
return zero_impl<T>(0);
}
};
template<>
struct zero<std::string>
{
constexpr static const char* get()
{ return "[Empty]"; }
};
Maybe:
#include <iostream>
#include <vector>
template <typename T>
inline T zero() {
return T();
}
template <>
inline std::string zero<std::string>() {
return "[Empty]";
}
int main() {
std::vector<std::string> v(1, zero<std::string>());
std::cout << v[0] << '\n';
}
I have a half good news: I found a very simple way (leveraging SFINAE), however the output is not exactly what I expected :)
#include <iostream>
#include <string>
#include <vector>
// Meat
template <typename T, typename = decltype(T::Zero)>
auto zero_init_impl(int) -> T { return T::Zero; }
template <typename T>
auto zero_init_impl(...) -> T { return T{}; }
template <typename T>
auto zero_init() -> T { return zero_init_impl<T>(0); }
// Example
struct Special { static Special const Zero; std::string data; };
Special const Special::Zero = { "Empty" };
int main() {
std::vector<int> const v{3, zero_init<int>()};
std::vector<Special> const v2{3, zero_init<Special>()};
std::cout << v[0] << ", " << v[1] << ", " << v[2] << "\n";
std::cout << v2[0].data << ", " << v2[1].data << ", " << v2[2].data << "\n";
return 0;
}
As mentioned, the result is surprising was explained by dyp, we have to be careful not use std::initializer<int> by mistake and then read past the end:
3, 0, 0
Empty, Empty, Empty
Curly brace initialization yields a different result than regular brace initialization (see here) which gives the expected 0, 0, 0. So you have to use regular braces.

Is there a way to initialize a variable with a value based on the template type

I have a template class. The class has a private member variable which I like to have preset to a certain value which differs for each template type.
I was thinking about different constructors for different types, but since the constructor has no parameters I have no idea how to do it.
Is it possible anyway ?
Thanks,
Use a traits template and specialize it with the value. something like:
template <typename T, typename Traits = MyTraits<T> >
class MyClass {
public:
int Foo ()
{
return Traits::Value;
}
};
template <>
class MyTraits<SomeClass>
{
public:
static int Value = 1;
};
template <>
class MyTraits<AnotherClass>
{
public:
static int Value = 2;
};
You can do it with a specialization on the type, the easiest form is:
#include <iostream>
template <typename T>
struct make {
static int value() {
return -1; // default
}
};
template <>
struct make<int> {
static int value() {
return 1;
}
};
template <>
struct make<double> {
static int value() {
return 2;
}
};
template <typename T>
struct foo {
const int val;
foo() : val(make<T>::value()) {}
};
int main() {
std::cout << foo<int>().val << ", " << foo<double>().val << "\n";
}
But you could also arrange it as an overload:
#include <iostream>
int value(void *) {
return -1; // default
}
int value(double *) {
return 2;
}
int value (int *) {
return 1;
}
template <typename T>
struct foo {
const int val;
foo() : val(value(static_cast<T*>(nullptr))) {}
};
int main() {
std::cout << foo<int>().val << ", " << foo<double>().val << "\n";
}
You could put the mapping from template parameters to values into a helper class, giving you something like this:
template<typename T> struct foo_helper;
template<> struct foo_helper<int> { static int getValue() {return 1; } };
template<> struct foo_helper<float> { static int getValue() {return 2; } };
....
template<typename T> class foo
{
int m;
foo():m(foo_helper<T>::getValue()){}
};