[ACCEPTED]-C++: How to use type in template function to branch?-template-function
While the solution proposed by Jason works, it's 8 far from idiomatic, and is harder to maintain 7 since the case
values in the switch
statement 1) have 6 no apparent meaning ("magic numbers") and 5 2) could easily get out of sync with the 4 values in the switch_value<>
specializations. I would 3 propose this instead:
struct Foo {
Foo() : iArr(), cArr() { }
template<typename T>
T get(std::size_t const idx) const {
return Foo::get_dispatcher<T>::impl(*this, idx);
}
private:
int iArr[10];
char cArr[10];
template<typename T>
struct get_dispatcher;
};
template<>
struct Foo::get_dispatcher<int> {
static int impl(Foo const& foo, std::size_t const idx) {
return foo.iArr[idx];
}
};
template<>
struct Foo::get_dispatcher<char> {
static char impl(Foo const& foo, std::size_t const idx) {
return foo.cArr[idx];
}
};
Invoking Foo::get<>
with any 2 type other than int
or char
will yield a compiler 1 error.
You would need to add a value structure 9 of some type you can use to get the values 8 for your switch-statement from. For instance:
template<typename T>
struct switch_value {};
template<>
struct switch_value<int>
{
enum { value = 1 };
};
template<>
struct switch_value<char>
{
enum { value = 2 };
};
//then inside you structure Foo
template <typename T>
T get( int idx )
{
switch ( switch_value<T>::value )
{
case 1:
return iArr[ idx ];
case 2:
return cArr[ idx ];
}
}
The 7 nice thing here is this should throw a compiler 6 error if you use a type that does not have 5 a valid value since the default version 4 of switch_value<T>
does not define a member value
, so if you 3 haven't specialized the structure for a 2 specific type, then such a template instantiation 1 will fail.
All of these answers are wayyyy overkill.
template <typename T>
T get( int idx )
{
if ( boost::is_same<T, int>::value)
return *(T*)&iArr[ idx ];
else
return *(T*)&cArr[ idx ];
}
0
You could specialise the member function:
struct foo
{
int iArr[10];
char cArr[10];
template<typename T>
T &get(int ipos) { assert( false && "Foo.get: Invalid type!" ); return T(); }
template<>
int &get<int>(int ipos) { return iArr[ipos]; }
template<>
char &get<char>(int ipos) {return cArr[ipos]; }
// add more specialisations for any other types...
};
Works 3 with msvc++ 2010. Hope this helps.
The switch 2 specialisation suggested by Jason should 1 also work fine.
This is probably overkill for your example, but 8 if you really only need to store one array 7 at a time, then you can use the boost::variant 6 class and a visitor, e.g.,
#include <boost/variant.hpp>
#include <iostream>
template< typename T >
class GetVisitor : public boost::static_visitor<T>
{
public:
GetVisitor(int index) : index_(index) {};
template <typename U >
T operator() (U const& vOperand) const
{
return vOperand[index_];
}
private:
int index_;
};
int main ()
{
int iArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
char cArr[10] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
boost::variant<int*, char*> intVariant(iArr); //- assign integer array to variant
boost::variant<int*, char*> charVariant(cArr); //- assign character array to another variant
int testInt = boost::apply_visitor(GetVisitor<int>(2), intVariant);
char testChar = boost::apply_visitor(GetVisitor<char>(9), charVariant);
std::cout << "returned integer is " << testInt << std::endl;
std::cout << "returned character is " << testChar << std::endl;
return 0;
}
output is:
returned integer is 3
returned character is j
The restriction 5 on the variant implied by the GetVisitor 4 class is that all members of the variant 3 must implement:
T operator[](int)
So you could also add, e.g., std::vector 2 and std::deque as potential members of the 1 variant.
I assume this is what you want beside just 2 focusing on template function:
in a .h file
template < typename T >
struct Foo
{
T arr[10];
T get( int idx )
{
return arr[ idx ];
}
};
somewhere 1 you use it like:
Foo<int> foo1;
Foo<char> foo2;
int i = foo1.get( 2 );
char c = foo2.get( 4 );
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.