I'm trying to improve my C++ template metaprogramming skills. From my understanding, I can't partially specialize a function(either member function or not). So, I need to define another class that can be used as template class, which enables us partially specialize template argument.
So, In order to check my understanding, I've wrote a simple code. It uses general template class and partially specialized template class to deal with various types. (I've tested this code using gcc 4.8 / clang 3.4 / MSVC 2015) It would give a result as follows:
Generic
Specialization for std::string
Specialization for bool
Specialization for integral type
Am I doing write using class templates? I need a review for this. Any comment would be helpful.
// a.hpp
#ifndef A_HPP
#define A_HPP
#include <iostream>
#include <string>
#include <type_traits>
// declaration & implementation for bar_impl::bar
template <typename T, typename T1, typename T2, typename T3>
struct bar_impl
{
static void bar(const T& input)
{
(void)input;
std::cout << "Generic" << std::endl;
}
};
template <typename T>
struct bar_impl<T, std::false_type, std::true_type, std::false_type>
{
static void bar(const T& input)
{
(void)input;
std::cout << "Specialization for integral type" << std::endl;
}
};
template <typename T>
struct bar_impl<T, std::false_type, std::true_type, std::true_type>
{
static void bar(const T& input)
{
(void)input;
std::cout << "Specialization for bool" << std::endl;
}
};
template <typename T, typename T1, typename T2>
struct bar_impl<T, std::true_type, T1, T2>
{
static void bar(const T& input)
{
(void)input;
std::cout << "Specialization for std::string" << std::endl;
}
};
struct Foo
{
template <typename T>
void bar(const T& input);
};
template <typename T>
void Foo::bar(const T& input)
{
bar_impl<
T,
typename std::is_same<T, std::string>::type,
typename std::is_integral<T>::type,
typename std::is_same<T, bool>::type
>::bar(input);
}
#endif // A_HPP
// b.cpp
#include "a.hpp"
int main()
{
Foo foo;
foo.bar(Foo());
foo.bar(std::string());
foo.bar(bool());
foo.bar(int());
return 0;
}