Use one namespace or another in function of a template parameter - c++

I want to use the implementation of std::pow (from cmath) in some cases, and in other cases, I want to use myspace::pow.
namespace myspace
{
template <typename T>
T pow(T val, unsigned exp)
{
if (exp == 0) return 1;
return val*pow(val,exp-1);
}
}
The different cases are determined by a template parameter.
template <typename T>
void myFunction()
{
auto val = pow(2.1,3);
/* ... */
}
If T == double, I want val to be calculated with std::pow. If T == mydouble, I want val to be calculated with myspace::pow. Now, I have a lot of lines like auto val = pow(2.1,3);, and I would like to avoid to check for the type of T for each line of code.
struct mydouble { /* ... */ };
myFunction<double>(); // uses std::pow
myFunction<mydouble>(); // uses myspace::pow
I've been breaking my head over this, but I can't find a solution. Any suggestions?

There are several solutions I could suggest.
Class Dispatcher (C++11)
Just implement a functor which picks the correct implementation in accordance with its templated type:
template <typename T>
struct PowerAdapter {
auto operator()(const T& arg, const T& exp) const {
return std::pow(arg, exp);
}
};
template <>
struct PowerAdapter<myspace::MyDouble> {
auto operator()(const myspace::MyDouble& arg, unsigned exp) const {
return myspace::pow(arg, exp);
}
};
And you can use it as follows:
template <typename T>
void myFunction(const T& t) {
using Pow = PowerAdapter<T>;
auto val = Pow{}(t, t);
// ...
}
Complete Code Example
Argument-Dependent Lookup (C++98)
If your class MyDouble is in the same namespace of your pow then you can just use this C++ rule:
[...] function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.
So the code:
template <typename T>
void myFunction(const T& t) {
pow(t, 12);
}
will select the proper pow in accordance with the namespace of T.
Note that, in case of double, you want to select the pow from math.h in the global namespace (unqualified name lookup).
Complete Code Example
I personally don't like this approach because it hides the selection mechanism and it's more difficult to extend.
if constexpr (C++17)
You can pick a proper branch at compile time.
Wrap your select logic into a proper function (or functor). Something like:
template <typename T, typename U>
auto PowerAdapter(const T& val, const U& exp) {
if constexpr (std::is_same_v<T, myspace::MyDouble>) {
return myspace::pow(val, exp);
} else {
return std::pow(val, exp);
}
}
Complete Code Example

Using Argument-dependent lookup you can achieve this easily
namespace ns
{
template <typename T>
auto pow(T val, unsigned exp)
{
using std::pow;
std::cout << __FUNCTION__ << '\n';
return pow(val, exp);
}
}
struct mydouble
{
double d;
};
mydouble pow(mydouble val, unsigned exp)
{
std::cout << __FUNCTION__ << '\n';
return val;
}
int main()
{
ns::pow(mydouble{ 3.14 }, 2); // runs pow
ns::pow(4, 2); // runs std::pow
}

Related

Compiler differences with use of templated overloads

I have a pretty specific situation where I'm feeding a bunch of data to a hasher-like class. In particular, one data type that I use has a member whose type depends on the supertype's type parameter. Long story short, here's a piece of code that illustrates this behaviour :
#include <assert.h>
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
// Some dummy priority structs to select overloads
struct priority0 { };
struct priority1 : priority0 { };
// This is the hasher-like function
struct Catcher
{
// Ideally we feed everything to this object through here
template <typename T> Catcher& operator<<(const T& v)
{
add(v, priority1{}); // always attempt to call the highest-priority overload
return *this;
}
// For floating-point data types
template <typename T> auto add(const T& v, priority1) -> std::enable_if_t<std::is_floating_point_v<T>, void>
{
std::cout << "caught float/double : " << v << std::endl;
}
// For ranges
template <class T> auto add(const T& range, priority1) -> decltype(begin(range), end(range), void())
{
for(auto const& v : range)
*this << v;
}
// For chars
void add(char c, priority1)
{
std::cout << c;
std::cout.flush();
}
// When everything else fails ; ideally should never happen
template <typename T> void add(const T& v, priority0)
{
assert(false && "should never happen");
}
};
// The one data type. Notice how the primary template and the
// specialization have a `range` member of different types
template <class T> struct ValueOrRange
{
struct Range
{
T min;
T max;
};
Range range;
T value;
};
template <> struct ValueOrRange<std::string>
{
std::vector<std::string> range;
std::string value;
};
// Overload operator<< for Catcher outside of the
// class to allow for processing of the new data type
// Also overload that for `ValueOrRange<T>::Range`. SFINAE should make sure
// that this behaves correctly (?)
template <class T> Catcher& operator<<(Catcher& c, const typename ValueOrRange<T>::Range& r)
{
return c << r.min << r.max;
}
template <class T> Catcher& operator<<(Catcher& c, const ValueOrRange<T>& v)
{
return c << v.range << v.value;
}
int main(int argc, char *argv[])
{
ValueOrRange<std::string> vor1{{}, "bleh"};
ValueOrRange<float> vor2{{0.f, 1.f}, 0.5f};
Catcher c;
c << vor1; // works fine, displays "bleh"
c << vor2; // fails the assert in Catcher::add(const T&, priority0) with T = ValueOrRange<float>::Range
return 0;
}
While the line c << vor1 gets resolved correctly through the various overloads and has the intended effect, the second line c << vor2 fails the assert.
What I want to happen : c << vor2 calls Catcher& operator<<(Catcher& s, const ValueOrRange<float>& v), which in turn calls Catcher& operator<<(Catcher& s, const typename ValueOrRange<float>::Range& r)
What does happen : instead of Catcher& operator<<(Catcher& s, const typename ValueOrRange<float>::Range& r), it is Catcher& Catcher::operator<<(const T& v) with T = typename ValueOrRange<float>::Range that is called, and thus the assert fails.
Worthy of note is that this same code has the intended effect on MSVC, and fails the assert on GCC.
Any idea on how I should fix that ?
Thanks to feedback from Igor Tandetnik, I got rid of the ::Range-specific overload and simply went for checking std::is_same_v<T, std::string>. A little less modular than I'd like, but it'll do the trick.
// A single function will do the trick
template <class T> Catcher& operator<<(Catcher& c, const ValueOrRange<T>& v)
{
if constexpr (std::is_same_v<T, std::string>)
c << v.range;
else
c << v.range.min << v.range.max;
return c << v.value;
}
In Catcher& operator<<(Catcher& c, const typename ValueOrRange<T>::Range& r), T in non deducible.
One work around would be friend function:
template <class T> struct ValueOrRange
{
struct Range
{
T min;
T max;
friend Catcher& operator<<(Catcher& c, const Range& r)
{
return c << r.min << r.max;
}
};
Range range;
T value;
};
Demo

How to make a C++ templated function agnostic to the return type for future specialization

I would like to have a general templated function declaration for which I do not know (already) the return type, similar to:
**template <class T> auto getIds() noexcept -> std::vector<Any>;**
The function could then be specialized with several input types, and a return type based on it:
template <> auto getIds<MyClass>() noexcept -> std::vector<decltype(MyClass::id)>
{
// implementation here.
}
And finally call it without to set the return:
auto val = getIds<MyClass>();
Is that possible? How?
Notes:
What I want to avoid is to have to set manually the Id type in the call function:
auto val = getIds<MyClass, decltype(MyClass::id)>(); // Ugly
I also discard any (non based on template) solution like extending all types from a RootMyClass. Is not that these solutions are bad, but they miss the point of this question.
Trying to be a bit clearer:
If I wrote
class MyClass { public: int id1=4;};
template <class T, class Id> auto getIds() -> Id;
template <> auto getIds<MyClass, decltype(MyClass::id1)>() -> decltype(MyClass::id1)
{
return 1;
}
auto main() -> int
{
getIds<MyClass>(); // Do not compile
getIds<MyClass, decltype(MyClass::id1)>(); // Compile but ugly
}
I would like the return type to be implicit, but I did not found a way to achieve that with specializations:
template <class T> getIds() noexcept -> WHICH TYPE?;
You cannot change the return type in a specialization, unfortunately. What you can do is change the return type in different overloads. Obviously. Furthermore, function template specializations are much more complicated than function overloads anyway, so let's do that.
Introduce an empty type wrapper, say:
template <typename T> struct wrapper { };
And forward the default implementation to that (I'm assuming C++14 here, otherwise you could wrap that in decltype() with a trailing return):
template <typename T>
auto getIds() { return getIds(wrapper<T>{}); }
Declare the generic version as:
template <typename T>
void getIds(wrapper<T> );
Don't define it. Then, anytime somebody tries to do:
auto ids = getIds<X>();
If there is no overload, that will simply fail to compile as you cannot assign from void. Then, you can overload as you see fit:
std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{ ... }
FINAL EXAMPLE:
#include <iostream>
#include <vector>
template <typename T> struct wrapper { };
template <typename T>
auto getIds() -> decltype(getIds(wrapper<T>{}))
{
return getIds(wrapper<T>{});
}
template <typename T>
void getIds(wrapper<T> ) { }
struct MyClass {
int id;
};
std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{
return {1, 2, 3};
}
int main()
{
for (auto id : getIds<MyClass>()) {
std::cout << id << " ";
}
}
This is actually very similar to Haskell typeclasses, and, surprisingly, works. For real usage I would use functors to allow partial specializations, though.
#include <iostream>
template<typename T>
decltype(T::x) getX(T const& t) { return; }
class A { public: int x; A(int x):x(x){} };
template<> int getX<A>(A const& a) {
return a.x;
}
class B { public: std::string x; B(std::string x):x(std::move(x)){} };
template<> std::string getX<B>(B const& b) {
return b.x;
}
int main() {
A a(42);
B b("43");
std::cout << getX(a) << std::endl;
std::cout << getX(b) << std::endl;
}
As you can see, each specialization has to (can?) provide the return type explicitly. decltype(A::x) (and B::x), respectively) could be used instead if you so prefer.
To make it even more Haskell-ish, you could expect a type tag in the type itself (basically a type family):
template<typename T>
typename T::TypeOfX getX(T const& t) { return; }
And consequently:
class A {
using TypeOfX = int;
TypeOfX someComplexLogicToGetX();
};
Both solutions to the type being instantiated for the actual type, except one gets it from a type of a field, and the other from a direct "type variable".

c++ power of integer, template meta programming

I want to make a function which returns a power of integer.
Please read the fmuecke's solution in
power of an integer in c++ .
However, I want to generalize his solution to the arbitrary type T.
Since c++11 has constexpr, I guess this is possible.
Naively, I tried something like,
template<class T, int N>
inline constexpr T pow(const T x){
return pow<N-1>(x) * x;
}
template<class T>
inline constexpr T pow<T, 1>(const T x){
return x;
}
template<class T>
inline constexpr T pow<T, 0>(const T x){
return 1;
}
Actually this approach failed since the partial specialization for function template is not allowed.
And one more question. I heard that it is up to the compiler whether the constexpr function is evaluated in compile time or not.
How do I force it to compute for general type.
I read from somewhere that one of the simplest hack for integral consts is to wrap it in std::integral_const::value.
Solution using recursion:
#include <iostream>
template<class T>
inline constexpr T pow(const T base, unsigned const exponent)
{
// (parentheses not required in next line)
return (exponent == 0) ? 1 : (base * pow(base, exponent-1));
}
int main()
{
std::cout << "pow(2, 4): " << pow(2, 4) << std::endl;
std::cout << "pow(5, 0): " << pow(5, 0) << std::endl;
}
Jeremy W. Murphy suggested/requested a version using exponentiation by squaring:
template<class T>
inline constexpr T pow(const T base, unsigned const exponent)
{
// (parentheses not required in next line)
return (exponent == 0) ? 1 :
(exponent % 2 == 0) ? pow(base, exponent/2)*pow(base, exponent/2) :
base * pow(base, (exponent-1)/2) * pow(base, (exponent-1)/2);
}
"I heard that it is up to the compiler whether the constexpr function is evaluated in compile time or not."
True, AFAIK. The compiler isn't required to do constant-initialization at compile-time, but if you use the result of a constexpr function as a non-type template argument, it has to compute the result at compile-time.
std::cout << std::integral_constant<int, pow(2, 4)>::value << std::endl;
Also see the approach using integral_constant as parameter of pow in Andy Prowl's answer.
Here's how you can enforce compile-time evaluation:
#include <iostream>
#include <type_traits>
// insert a constexpr `pow` implementation, e.g. the one from above
template < typename T, T base, unsigned exponent >
using pow_ = std::integral_constant < T, pow(base, exponent) >;
// macro == error prone, you have been warned
#define POW(BASE, EXPONENT) (pow_ < decltype(BASE), BASE, EXPONENT > :: value)
int main()
{
std::cout << "pow(2, 4): " << pow_<int, 2, 4>::value << std::endl;
std::cout << "pow(2, 4): " << POW(2, 4) << std::endl;
}
Please leave a comment if you downvote so I can improve my answer.
When you find yourself in need of partially specializing a function template (beware, this does not mean that in this case you are in need, as DyP's answer shows), you may either resort to overloading (see the last update at the end of this answer) or, if that's not possible, wrap that function template into a class template, and have a static, non-template member function replace your original function template (and its specializations):
namespace detail
{
template<class T, int N>
struct helper
{
static constexpr T pow(const T x){
return helper<T, N-1>::pow(x) * x;
}
};
template<class T>
struct helper<T, 1> // Unnecessary specialization! (see the edit)
{
static constexpr T pow(const T x){
return x;
}
};
template<class T>
struct helper<T, 0>
{
static constexpr T pow(const T x){
return 1;
}
};
}
Then, you could provide a helper function template that delegates to the specialization of your helper class template:
template<int N, class T>
T constexpr pow(T const x)
{
return detail::helper<T, N>::pow(x);
}
Here is a live example.
EDIT:
Notice, that the specialization for N == 1 is actually not necessary. I kept it in the original text because the purpose of this answer was mainly to show how to workaround the impossibility of partially specializing function templates in general - so I translated the original program piece-by-piece.
As noted by Dyp in the comments, however, this would be enough:
namespace detail
{
template<class T, int N>
struct helper
{
static constexpr T pow(const T x){
return helper<T, N-1>::pow(x) * x;
}
};
template<class T>
struct helper<T, 0>
{
static constexpr T pow(const T x){
return 1;
}
};
}
UPDATE:
As a further remark, please keep in mind that even when you can specialize function templates (e.g. with explicit - not partial - specializations), it is generally not a good idea to do so, because function template specialization does not normally behave as one would expect.
Most of those situations that may seem to ask for function template specialization can actually be achieved through overloading, powered by well-known techniques such as tag dispatching. An example is proposed by Potatoswatter in the comments, pointing out that std::integral_constant could be used in this situation:
template<class T>
inline constexpr T pow(const T x, std::integral_constant<int, 0>){
return 1;
}
template<class T, int N>
inline constexpr T pow(const T x, std::integral_constant<int, N>){
return pow(x, std::integral_constant<int, N-1>()) * x;
}
template<int N, class T>
inline constexpr T pow(const T x)
{
return pow(x, std::integral_constant<int, N>());
}
However, all these guidelines on "how to solve problems that seem to require function template partial specialization" should be taken into consideration when they are really needed. In this concrete case, as DyP showed in his answer, they are not.
Here is a solution with a single function:
template <int N, class T>
constexpr T pow(const T& x)
{
return N > 1 ? x*pow<(N-1)*(N > 1)>(x)
: N < 0 ? T(1)/pow<(-N)*(N < 0)>(x)
: N == 1 ? x
: T(1);
}
Here is a simple solution:
#include<bits/stdc++.h>
using namespace std;
template<int N, int M>
struct Pow
{
enum { res = N * Pow<N,M-1>::res};
};
template<int N>
struct Pow<N,0>
{
enum {res = 1};
};
int main()
{
cout<<Pow<2,3>::res<<"\n";
}
Clean and simple solution here:
#include <cstddef>
template<size_t N, size_t P>
struct pow_constexpr { constexpr static auto value = N * pow_constexpr<N, P-1>::value; };
template<size_t N>
struct pow_constexpr<N, 1> { constexpr static auto value = N; };
template<size_t N>
struct pow_constexpr<N, 0> { constexpr static auto value = 1; };
int main() {
return pow_constexpr<2, 30>::value; // 1073741824
}

What's a good way to implement an array of instances to different types

I'm writing myself a math library making heavy use of templates, especially variadic templates, and would like to implement a Sum functor that can take any number of functors of different types and store them. I would also like to avoid any dynamic memory allocation (as an exercise to myself mostly, I have nothing against dynamic memory allocation in general).
The problem I couldn't find any help on is how to store in a class instances to different types. Something like:
any_array<Types...> a = {Type1(), Type2(), Type3(), ...};
with some way of iterating through a getting the proper type for each value. Using boost would not be an issue as I'm already using it elsewhere.
I have come up with a solution that seems to work well, but I'd like to see what other ways there might be to approach this problem.
My solution to this is a class that essentially looks like (a fully compiling implementation and example can be found below):
template <class ... Functions>
class Sum
{
char functions[num_bytes<Functions...>::value];
template <class Next, class ... Others>
void SetFunctions(int offset, Next f, Others ... others)
{
Next * p = (Next*)(functions + offset);
*p = f;
SetFunctions(offset + sizeof(Next), others...);
}
template <class Last>
void SetFunctions(int offset, Last f)
{
Last * p = (Last*)(functions + offset);
*p = f;
}
public:
Sum(Functions ... funcs)
{
SetFunctions(0, funcs...);
}
};
I like this solution in that it should be easily generalizable to any sort of accumulation functor I could want and the implementation underneath is kept hidden from the user. I'm not sure about storing the raw bytes to these objects but can't think of anything wrong with that per se. The possibility of this being generalized leads me to suspect that it has already been implemented somewhere but I couldn't find anything in my own search.
FWIW here's a full example of my implementation:
#include <functional>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/mpl/accumulate.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/int.hpp>
#include <iostream>
#include <boost/utility/enable_if.hpp>
using namespace boost::mpl::placeholders;
using namespace boost::mpl;
//Returns the sum of the number of bytes each class takes up.
//This is used as the size of the array we need to create.
template <class ... Args>
struct num_bytes :
boost::mpl::accumulate<vector<Args...>,
int_<0>,
plus<_1, sizeof_<_2> > >::type
{
};
template <class ... Args>
struct empty_list
{
typedef empty_list type;
static const bool value = sizeof...(Args) == 0;
};
template <class ... Functions>
class Sum
{
public:
Sum(Functions ... functions)
{
SetFunctions(0, functions...);
}
inline double operator()(double x)
{
return evaluate<Functions...>(0, x);
}
private:
template <class Next, class ... Others>
inline void SetFunctions(int offset, Next f, Others ... funcs)
{
Next * p = (Next*)(functions + offset);
*p = f;
SetFunctions(offset + sizeof(Next), funcs...);
}
template <class Last>
inline void SetFunctions(int offset, Last f)
{
Last * p = (Last*)(functions + offset);
*p = f;
}
//Because we are not passing our function objects down, we
//have to manually disable this function overload to end the recursive
//instantiations of this function.
template <class Next, class ... Others>
inline double evaluate(int offset, double x,
typename boost::enable_if_c<!empty_list<Others...>::value>::type * dummy = NULL)
{
Next * p = (Next*)(functions + offset);
return evaluate<Others...>(offset + sizeof(Next), x) + (*p)(x);
}
template <class Last>
inline double evaluate(int offset, double x)
{
Last * p = (Last*)(functions+offset);
return (*p)(x);
}
char functions[num_bytes<Functions...>::value];
};
//Function to help initialize a Sum object
template <class ... Functions>
Sum<Functions...> GetSum(Functions ... functions)
{
return Sum<Functions...>(functions...);
}
//return function object of the form f(x) = x + n.
std::binder2nd<std::plus<int> > GetTestFunction(int n)
{
return std::bind2nd(std::plus<int>(), n);
}
int main()
{
auto sum = GetSum(GetTestFunction(0),
GetTestFunction(1),
GetTestFunction(2));
std::cout << sum(0) << ' ' << sum(1) << std::endl;
return 0;
}
Which outputs: 3 6 when run.
NOTE: I could not get this compile with a gcc-4.6, only gcc-4.7 and I used the command line:
g++-4.7 -std=c++0x test_sum.cpp -Wall
It seems to me that what you need is a std::tuple:
template <class ... Functions>
class Sum
{
std::tuple<Functions...> functions;
public:
Sum(Functions&& ... funcs)
: functions( std::forward< Functions >( funcs )... )
{
}
};
I don't know if it's a good way, but it's a way:
#define BOOST_RESULT_OF_USE_DECLTYPE
#include <functional>
#include <iostream>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/fold.hpp>
#include <boost/phoenix.hpp>
namespace fusion=boost::fusion;
namespace phx=boost::phoenix;
template <class ... Functions>
class Sum
{
public:
Sum(Functions ... functions):functions_(functions...)
{
}
inline double operator()(double x)
{
return fusion::fold(functions_,0,eval(x));
}
private:
template <typename Arg>
struct evaluate
{
evaluate(const Arg& arg):arg_(arg){}
template <typename State, typename Func>
State operator()(State const& current_state, const Func& f)
{
return current_state + f(arg_);
}
Arg arg_;
};
template <typename Arg>
evaluate<Arg> eval(const Arg& arg)
{
return evaluate<Arg>(arg);
}
fusion::vector<Functions...> functions_;
};
//Function to help initialize a Sum object
template <class ... Functions>
Sum<Functions...> GetSum(Functions ... functions)
{
return Sum<Functions...>(functions...);
}
//return function object of the form f(x) = x + n.
std::binder2nd<std::plus<int> > GetTestFunction(int n)
{
return std::bind2nd(std::plus<int>(), n);
}
struct plus_two
{
double operator()(double arg) const
{
return arg+2;
}
};
int main()
{
auto sum = GetSum(GetTestFunction(0),
phx::arg_names::_1+1,
plus_two());
std::cout << sum(0) << ' ' << sum(1) << std::endl;
return 0;
}

template specialization according to sizeof type

I would like to provide a templated function, that varies its implementation (->specialization) according to the sizeof the template type.
Something similar to this (omitted typecasts), but without the if/elseif:
template<class T>
T byteswap(T & swapIt)
{
if(sizeof(T) == 2)
{
return _byteswap_ushort (swapIt);
}
else if(sizeof(T) == 4)
{
return _byteswap_ulong(swapIt);
}
else if(sizeof(T) == 8)
{
return _byteswap_uint64(swapIt);
}
throw std::exception();
}
I know there are many roads to reach my goal, but since I try to learn about SFINAE and type traits I'm particularly interested in solutions using those techniques to decide at compile time which specialization to choose and which calls are not admitted.
Perhaps implementing a class trait is_4ByteLong and using boost::enable_if...
I have to admit, I'm stuck right now, so I thank you for any help or advice
You don't need SFINAE or type traits. Vanilla template specialization is enough. Of course it must be specialized on structs as C++(98) doesn't support function template partial specialization.
template <typename T, size_t n>
struct ByteswapImpl
/*
{
T operator()(T& swapIt) const { throw std::exception(); }
}
*/ // remove the comments if you need run-time error instead of compile-time error.
;
template <typename T>
struct ByteswapImpl<T, 2> {
T operator()(T& swapIt) const { return _byteswap_ushort (swapIt); }
};
// ...
template <typename T>
T byteswap(T& swapIt) { return ByteswapImpl<T, sizeof(T)>()(swapIt); }
Simply make an auxiliary class that takes the size as a template argument:
#include <cstddef>
#include <iostream>
template<std::size_t Size>
struct ByteSwapper { };
template<>
struct ByteSwapper<2> {
static unsigned short swap(unsigned short a) {
return 2 * a;
}
};
template<typename T>
T byteswap(const T& a) {
return ByteSwapper<sizeof(T)>::swap(a);
}
int main() {
unsigned short s = 5;
std::cout << byteswap(s) << std::endl;
unsigned int i = 7;
// std::cout << byteswap(i) << std::endl; // error
}
Just for the sake of demonstrating enable_if in action, since you spoke about it:
template <class T>
typename boost::enable_if_c< sizeof(T) == 2, T >::type
swapIt(T& rhs) { return _byteswap_short(rhs); }
template <class T>
typename boost::enable_if_c< sizeof(T) == 4, T >::type
swapIt(T& rhs) { return _byteswap_long(rhs); }
etc...
And of course, instead of throwing, there is just no implementation if the type doesn't meet any of the requirement and thus you have a compile time error.
Two notes:
Use of typename and ::type are mandatory
I used enable_if_c because my expression evaluates to a boolean value directly, whereas enable_if requires a type containing a ::value member which is a boolean.
I can propose the following method:
Its benefit is that you don't have to throw an exception if the operand isn't of the valid size. It just won't link. So that you have the error checking at build time.
template<int size>
void byteswapInPlace(void* p);
template<> void byteswapInPlace<1>(void* p) { /* do nothing */ }
template<> void byteswapInPlace<2>(void* p)
{
_byteswap_ushort((ushort*) p);
}
template<> void byteswapInPlace<4>(void* p)
{
_byteswap_ulong((ulong*) p);
}
template<> void byteswapInPlace<8>(void* p)
{
_byteswap_uint64((uint64*) p);
}
template<class T>
T byteswap(T & swapIt)
{
byteswapInPlace<sizeof(T)>(&swapIt);
return swapIt;
}