Template partial specialization - c++

template<class T>
struct TypeX;
template<>
struct TypeX<int(...)>//HERE IF WITHOUT ELLIPSIS IT WILL COMPILE
{
static std::string get_type()
{
return "int()";
}
};
template<>
struct TypeX<int>
{
static std::string get_type()
{
return "int";
}
};
template<class T>
struct type_descriptor
{
typedef T type;
typedef typename std::remove_reference<T>::type no_ref_type;
typedef typename std::remove_pointer<no_ref_type>::type no_ref_no_pointer_type;
typedef typename std::remove_cv<no_ref_no_pointer_type>::type no_ref_no_pointer_no_cv_type;
typedef typename std::remove_all_extents<no_ref_no_pointer_no_cv_type>::type no_ref_no_pointer_no_cv_no_ext_type;
typedef no_ref_no_pointer_no_cv_no_ext_type bare_type;
enum {isArray = std::is_array<T>::value, isPointer = std::is_pointer<T>::value, isRef = std::is_reference<T>::value};
static std::string get_type()
{
return pointer_<isPointer>() + array_<std::is_array<no_ref_no_pointer_type>::value>() + TypeX<bare_type>::get_type();
}
};
template<bool C>
std::string array_()
{return "";}
template<>
std::string array_<true>()
{return "array of";}
template<bool C>
std::string pointer_()
{return "";}
template<>
std::string pointer_<true>()
{return "pointer to";}
int _tmain(int argc, _TCHAR* argv[])
{
cout << type_descriptor<int(*)()>::get_type();
return 0;
}
Please see comment in a code. The question is why if I specialize for ellipsis, which suppose to mean any number I'm getting an error, but when I specialize for no arguments it compiles?

The question is why if I specialize
for ellipsis, which suppose to mean
any number I'm getting an error, but
when I specialize for no arguments it
compiles?
Because ellipsis doesn't imply any number of parenthesis (as you're trying to use it in main) . ellipsis is used to imply variable number of arguments in function (C++03).
EDIT: Maybe the following example gives you enough hint to implement what you want to:
template<class T>
struct TypeX
{
TypeX() { cout << "TypeX" << endl; }
};
template<typename T>
struct TypeX<T(*)()> //will match with : int (*)(), char (*)(), etc!
{
TypeX() { cout << "TypeX<T(*)()>" << endl; }
};
template<typename T, typename S>
struct TypeX<T(*)(S)> //will match with : int (*)(int), char (*)(int), etc!
{
TypeX() { cout << "TypeX<T(*)(S)>" << endl; }
};
template<typename T, typename S, typename U>
struct TypeX<T(*)(S, U)> //will match with : int (*)(int, char), char (*)(int, int), etc!
{
TypeX() { cout << "TypeX<T(*)(S, U)>" << endl; }
};
int main() {
TypeX<int*>();
TypeX<int(*)()>();
TypeX<int(*)(int)>();
TypeX<int(*)(char)>();
TypeX<int(*)(char, int)>();
TypeX<int(*)(short, char)>();
return 0;
}
Output:
TypeX
TypeX<T(*)()>
TypeX<T(*)(S)>
TypeX<T(*)(S)>
TypeX<T(*)(S, U)>
TypeX<T(*)(S, U)>
Demo at ideone : http://www.ideone.com/fKxKK

An elipsis means the function can accept any number of arguments at each place of invocation.
int f(...); // signature
int x = f(); // invocations
int y = f(my_int, my_double);
The function signature itself is distinct from the more specific signatures naively implied by each invocation (i.e. int f(), int f(int, double)).
Therefore, while you can specialise for the int (*)(...) case, only a function type that actually specifies an initial elipsis will match. Other functions like int (*)(int) do not match.

Related

Template function deduction fail on std::conditional argument

Please, before marking this as a duplicate of This question read the entirety of the post
This piece of code fails to compile, with a template deduction error:
#include <iostream>
#include <type_traits>
template<typename T = float, int N>
class MyClass
{
public:
template<typename DATA_TYPE>
using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
MyType<T> Var;
void Foo()
{
Bar(Var);
}
template<typename TYPE>
void Bar(MyType<TYPE> Input)
{
std::cout << typeid(Input).name() << std::endl;
}
};
int main()
{
MyClass<float, 1> c;
c.Foo();
return 0;
}
I understand the point that was made in the question i linked above, which is that "the condition which allows to choose the type to be deduced depends on the type itself", however, why would the compiler fail in the specific case i provided as the condition here seems to be fully independent from the type, or is there something i'm missing?
I would be more than happy if someone could refer to a section of the c++ standard that would allow me to fully understand this behaviour.
As the linked question, TYPE is non deducible. MyType<TYPE> is actually XXX<TYPE>::type.
You have several alternatives, from your code, I would say one of
Bar no longer template:
template<typename T = float, int N>
class MyClass
{
public:
template<typename DATA_TYPE>
using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
MyType<T> Var;
void Foo()
{
Bar(Var);
}
void Bar(MyType<T> Input)
{
std::cout << typeid(Input).name() << std::endl;
}
};
requires (or SFINAE/specialization for pre-c++20):
template<typename T = float, int N>
class MyClass
{
public:
template<typename DATA_TYPE>
using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
MyType<T> Var;
void Foo()
{
Bar(Var);
}
template<typename TYPE>
void Bar(TYPE Input) requires(N > 0)
{
std::cout << typeid(Input).name() << std::endl;
}
void Bar(double Input) requires(N <= 0)
{
std::cout << typeid(Input).name() << std::endl;
}
};

Is it possible to use parameter pack to allow template function to accept equivalent types?

This question is related to one on SO a couple of years ago by Georg Fritzsche about transforming a parameter pack (Is it possible to transform the types in a parameter pack?). In the end, the individual types in the parameter pack can be transformed, e.g. by converting to corresponding pointer types.
I am wondering if it is possible to use this technique to write one standard function/functor and a set of wrapper functions (out of one template), so that the wrappers can take parameters of equivalent types and then call the standard function to do actual work.
Using the answer by Johannes Schaub - litb the original example below. Is it possible to write one template f, which can take any combinations of int/int*,char/char* and call a common function f_std(int*,char*) to do the work. (The number of parameters is not pre-specified.)
--- Update ---
For example, given int i; char c;, is it possible to write a caller using pack transformation such that the following works
call_ptr(f_std,i,c);
call_ptr(f_std,&i,c);
call_ptr(f_std,i,&c);
What I've tried so far is listed below (updated to clarify.). Basically, I tried to accept an list of not necessarily pointer types and convert them to pointer types, before making call to a std::function that takes pointer types. But the code does not compile. I don't know how to write a helper function to accept one function with a standard signature, but accept a parameter pack of something else.
Thanks in advance
#include <type_traits>
#include <functional>
using namespace std;
template<class... Args> struct X {};
template<class T> struct make_pointer { typedef T* type; };
template<class T> struct make_pointer<T*> { typedef T* type; };
template<template<typename...> class List,
template<typename> class Mod,
typename ...Args>
struct magic {
typedef List<typename Mod<Args>::type...> type;
};
/////////////////
// trying to convert parameter pack to pointers
template<class T> T* make_ptr(T x) { return &x; }
template<class T> T* make_ptr(T* x) { return x; }
template <typename Value, typename ...Args>
class ByPtrFunc
{
public:
typedef typename magic<X, make_pointer, Args...>::type PArgs;
Value operator()(Args... args) { return f(make_ptr(args)...); }
private:
std::function<Value (PArgs...)> _ptr_func;
}; //ByPtrFunc
//helper function to make call
template<typename A, typename ...Args>
static A call_ptr(std::function<A (Args...)> f, Args... args) {
return ByPtrFunc<A, Args...>{f}(args ...);
}
int main() {
typedef magic<X, make_pointer, int*, char>::type A;
typedef X<int*, char*> B;
static_assert(is_same<A, B>::value, ":(");
int i=0; char c='c';
function<int (int* pa,char* pb)> f_std = [](int* pa,char* pb)->int {return *pa + * pb;};
f_std(&i,&c);
//////////////////
//Is the following possible.
call_ptr(f_std,i,c);
call_ptr(f_std,&i,c);
call_ptr(f_std,i,&c);
return 0;
}
This answers your question syntax-wise, if I've understood it correctly: yes, it's possible.
// given int or char lvalue, returns its address
template<class T>
T* transform(T& t) {
return &t;
}
// given int* or char*, simply returns the value itself
template<class T>
T* transform(T* t) {
return t;
}
// prints out the address corresponding to each of its arguments
void f_std() {
}
template<class Arg, class... Args>
void f_std(Arg arg, Args... args) {
std::cout << (void*)arg << std::endl;
f_std(args...);
}
// converts int to int*, char to char*, then calls f_std
template<class... Args>
void f(Args... args) {
f_std(transform(args)...);
}
Unfortunately, calling f will pass int and char arguments by value, and hence copy them. To fix this, use perfect forwarding in the definition of f:
template<class... Args>
void f(Args&&... args) {
f_std(transform(std::forward<Args>(args))...);
}
Driver:
int main() {
int x = 1;
char c = 'a';
cout << (void*)&x << endl;
cout << (void*)&c << endl;
f(x, &x, c, &c);
}
Output (example; ran it on my machine just now):
0x7fff36fb5ebc
0x7fff36fb5ebb
0x7fff36fb5ebc
0x7fff36fb5ebc
0x7fff36fb5ebb
0x7fff36fb5ebb
Following may help:
template <typename T> T* make_pointer(T& t) { return &t; }
template <typename T> T* make_pointer(T* t) { return t; }
template <typename Ret, typename... Args, typename ...Ts>
Ret call_ptr(std::function<Ret (Args*...)> f, Ts&&...args)
{
static_assert(sizeof...(Args) == sizeof...(Ts), "Bad parameters");
f(make_pointer(std::forward<Ts>(args))...);
}
Now, use it:
void f_std(int*, char*) { /* Your code */ }
int main(int argc, char *argv[])
{
int i;
char c;
std::function<void (int*, char*)> f1 = f_std;
call_ptr(f1, i, c);
call_ptr(f1, i, &c);
call_ptr(f1, &i, c);
call_ptr(f1, &i, &c);
return 0;
}
For reference, below is what worked for me, based on the accepted answer #Jarod42 and the type transformation "magic". slightly more general and with added type checking. Turns out type-transformation is simply a pattern expansion.
#include <type_traits>
#include <functional>
#include <iostream>
using namespace std;
/////////////////
// convert parameter pack to pointers
//types
template<class T> struct make_ptr_t { typedef T* type; };
template<class T> struct make_ptr_t<T*> { typedef T* type; };
//values
template<class T> T* make_ptr(T& x) { return &x; }
template<class T> T* make_ptr(T* x) { return x; }
/////////////////////////////////////
// (optional) only for type checking
template<class... Args> struct X {};
template<template<typename...> class List,
template<typename> class Mod,
typename ...Args>
struct magic {
typedef List<typename Mod<Args>::type...> type;
};
//helper function to make call
template<typename A, typename ...PArgs, typename ...Args>
static A call_ptr(std::function<A (PArgs...)> f, Args... args) {
static_assert(is_same<X<PArgs...>,typename magic<X, make_ptr_t, Args...>::type>::value, "Bad parameters for f in call_ptr()"); //type checking
return f(make_ptr(args)...);
}
int main() {
int i=0; char c='c'; string s="c";
function<int (int* pa,char* pb)> f_std = [](int* pa,char* pb)->int {return *pa + * pb;};
f_std(&i,&c);
cout << call_ptr(f_std,i,c) << endl;
cout << call_ptr(f_std,&i,c) << endl;
cout << call_ptr(f_std,i,&c) << endl;
//cout << call_ptr(f_std,i,s) << endl; //complains about bad parameters.
return 0;
}

Invalid use of incomplete type (SFINAE)

I am trying to use some SFINAE inside a templated struct. I reduced my problem to the following and could make this work:
template<bool mybool>
struct test {
void myfunc();
};
template<bool mybool>
void test<mybool>::myfunc() {
std::cout << "test true" << std::endl;
}
template<>
void test<false>::myfunc() {
std::cout << "test false" << std::endl;
}
int main(int argc, char ** argv) {
test<true> foo;
test<false> bar;
foo.myfunc();
bar.myfunc();
}
With this code, I get the result:
test true
test false
However, if I want to consider that my struct test with more than one template parameter, I tried adapting the above like this:
template<int myint, bool mybool>
struct test {
void myfunc();
};
template<int myint, bool mybool>
void test<myint,mybool>::myfunc() {
std::cout << "test true" << std::endl;
}
template<int myint>
void test<myint,false>::myfunc() {
//error: invalid use of incomplete type 'struct test<myint, false>'
std::cout << "test false" << std::endl;
}
int main(int argc, char ** argv) {
test<1,true> foo;
test<1,false> bar;
foo.myfunc();
bar.myfunc();
}
I am getting an invalid use of incomplete type 'struct test'.
Am I going in the wrong direction? Is there a way to do what I want to do?
Thanks for your help!
You cannot partially specialize member function, you should partially specialize full struct. Following example will work correctly
template<int myint, bool mybool>
struct test {
void my_func();
};
template<int myint, bool mybool>
void test<myint,mybool>::my_func() {
std::cout << "test true" << std::endl;
}
template<int myint>
struct test<myint, false> {
void my_func();
};
template<int myint>
void test<myint,false>::my_func() {
//error: invalid use of incomplete type 'struct test<myint, false>'
std::cout << "test false" << std::endl;
}
int main(int argc, char ** argv) {
test<1,true> foo;
test<1,false> bar;
foo.my_func();
bar.my_func();
}
If you want to avoid redefining your class, which you would have to do since partial specialisation of (member) functions is not allowed, you could decompose your type. This will minimise the repetition of code:
template<int myint, bool mybool>
struct test {
char some_var;
std::vector<int> more_var;
void my_func();
};
Change to:
template<int myint>
struct test_static {
protected:
char some_var;
std::vector<int> more_var;
};
template <int myint, bool mybool>
struct test : private test_static<myint> {
void my_func() {
// default case
}
};
template <int myint>
struct test<myint,false> : private test_static<myint> {
void my_func() {
// special case
}
};
Of course, if you want full visibility of all members to the outside, don't make them protected in the first place and use public instead of private inheritance.
Looking first at this question on the SFINAE principle to refresh my memory, I tried to get the result you are looking for with minimal redundancy in the code.
I also checked the wikipedia article on the subject, which indicated me that you need a functionality similar too boost::enable_if to conditionally choose your function inmplementation:
// simplified version of boost::enable_if_c and disable_if_c to match your exact need
template <bool B>
struct enable_if_c {
typedef void type;
};
struct enable_if_c<false>{};
template <bool B>
struct disable_if_c {
typename void type;
};
struct disable_if_c<true> {};
template<bool mybool, typename T>
struct test {
template <bool d>
typename enable_if_c<d>::type my_func_impl(){
cout << "true" << endl;
}
template <bool d>
typename disable_if_c<d>::type my_func_impl(){
cout << "false" << endl;
}
void my_func(){ my_func_impl<mybool>(); }
};
You can define the my_func_impl bodies outside the struct with the following syntax:
template <bool mybool, typename T>
template <bool d>
typename enable_if_c<d>::type test<mybool,T>::my_func_impl(){
cout << "true" << endl;
}
The tricky point of the problem is that you cannot rely on a simple overloading, since you want the same function prototype, hence the need to exclusively define one or the other implementation.
You can add a little improvement to the answer provided by diderc, by just a little modification that enables you to avoid the use of an auxiliary function which would pollute your functions names :
Instead of :
template <bool d>
typename enable_if_c<d>::type my_func_impl(){
cout << "true" << endl;
}
template <bool d>
typename disable_if_c<d>::type my_func_impl(){
cout << "false" << endl;
}
void my_func(){ my_func_impl<mybool>(); }
Just write :
template <bool d = mybool>
typename enable_if_c<d>::type my_func(){
cout << "true" << endl;
}
template <bool d = mybool>
typename disable_if_c<d>::type my_func(){
cout << "false" << endl;
}
And if you can use C++11, then you can replace enable_if_c and disable_if_c by std::enable_if.
( I can't comment his answer, so I posted my own )

Overriding return type in function template specialization

I would like to specialize a function template such that the return type changes depending on the type of the template argument.
class ReturnTypeSpecialization
{
public:
template<typename T>
T Item();
};
// Normally just return the template type
template<typename T>
T ReturnTypeSpecialization::Item() { ... }
// When a float is specified, return an int
// This doesn't work:
template<float>
int ReturnTypeSpecialization::Item() { ... }
Is this possible? I can't use C++11.
Since the specialization has to agree with the base template on the return type, you can make it so by adding a "return type trait", a struct you can specialize and draw the true return type from:
// in the normal case, just the identity
template<class T>
struct item_return{ typedef T type; };
template<class T>
typename item_return<T>::type item();
template<>
struct item_return<float>{ typedef int type; };
template<>
int item<float>();
Live example.
Note that you might want to stick to the following, so you only need to update the return-type in the item_return specialization.
template<>
item_return<float>::type foo<float>(){ ... }
// note: No `typename` needed, because `float` is not a dependent type
Do all of the specialization in a worker class and use a simple function as a wrapper that will be specialized implicitly.
#include <iostream>
using std::cout;
// worker class -- return a reference to the given value
template< typename V > struct worker
{
typedef V const & type;
static type get( V const & v ) { return v; }
};
// worker class specialization -- convert 'unsigned char' to 'int'
template<> struct worker<unsigned char>
{
typedef int type;
static type get( unsigned char const & v ) { return v; }
};
// mapper function
template< typename V > typename worker<V>::type mapper( V const & v )
{
return worker<V>::get(v);
}
int main()
{
char a='A';
unsigned char b='B';
cout << "a=" << mapper(a) << ", b=" << mapper(b) << "\n";
}
In this example, the specialization of unsigned char causes it to be converted to an int so that cout will display it as a number instead of as a character, generating the following output...
a=A, b=66
Perhaps you could use the following hack. Given these simple type traits:
template<bool b, typename T, typename U>
struct conditional { typedef T type; };
template<typename T, typename U>
struct conditional<false, T, U> { typedef U type; };
template<typename T, typename U>
struct is_same { static const bool value = false; };
template<typename T>
struct is_same<T, T> { static const bool value = true; };
You could write your class and specialized member function as follows:
class ReturnTypeSpecialization
{
public:
template<typename T>
typename conditional<is_same<T, float>::value, int, T>::type
Item();
};
// Normally just return the template type
template<typename T>
typename conditional<is_same<T, float>::value, int, T>::type
ReturnTypeSpecialization::Item() { return T(); }
// When a float is specified, return an int
template<>
int ReturnTypeSpecialization::Item<float>() { return 1.0f; }
Simple test program (uses C++11 just for verification):
int main()
{
ReturnTypeSpecialization obj;
static_assert(std::is_same<decltype(obj.Item<bool>()), bool>::value, "!");
static_assert(std::is_same<decltype(obj.Item<float>()), int>::value, "!");
}
Here is a live example.
You can do template specializations like so:
template<typename T>
T item() {
return T();
}
template<>
float item<float>() {
return 1.0f;
}
Hi I tried to use the template specialization for returning the parameter value for primitives as well as std::string data, while doing so I was getting lot of unresolved external, redefinition kind of errors.
so if any one face something like this, he/she can use something like below when want to return different data types including string,
NOTE: both the Template function must be the part of the Header file (*.h)...
so we are using template specialization string data type here...
inside class as a inline member we have to use template specialize method and in the same file we can define the template as well.
class ConfigFileParser
{
public:
bool ParseConfigFile(const std::string& file_name);
template <typename T>
T GetParameterValue(const std::string key);
template <>
std::string GetParameterValue<std::string>(const std::string key)
{
std::string param_val = "";
//do logical operation here...
return param_val;
}
private:
// private functions...
// private data...
};
template <typename T>
T ConfigFileParser::GetParameterValue(const std::string key)
{
T param_val = 0;
std::stringstream ss;
std::string val_str;
// do some operation here...
ss << val_str.c_str();
ss >> param_val;
return param_val;
}

Why function template cannot be partially specialized?

I know the language specification forbids partial specialization of function template.
I would like to know the rationale why it forbids it? Are they not useful?
template<typename T, typename U> void f() {} //allowed!
template<> void f<int, char>() {} //allowed!
template<typename T> void f<char, T>() {} //not allowed!
template<typename T> void f<T, int>() {} //not allowed!
AFAIK that's changed in C++0x.
I guess it was just an oversight (considering that you can always get the partial specialization effect with more verbose code, by placing the function as a static member of a class).
You might look up the relevant DR (Defect Report), if there is one.
EDIT: checking this, I find that others have also believed that, but no-one is able to find any such support in the draft standard. This SO thread seems to indicate that partial specialization of function templates is not supported in C++0x.
EDIT 2: just an example of what I meant by "placing the function as a static member of a class":
#include <iostream>
using namespace std;
// template<typename T, typename U> void f() {} //allowed!
// template<> void f<int, char>() {} //allowed!
// template<typename T> void f<char, T>() {} //not allowed!
// template<typename T> void f<T, int>() {} //not allowed!
void say( char const s[] ) { std::cout << s << std::endl; }
namespace detail {
template< class T, class U >
struct F {
static void impl() { say( "1. primary template" ); }
};
template<>
struct F<int, char> {
static void impl() { say( "2. <int, char> explicit specialization" ); }
};
template< class T >
struct F< char, T > {
static void impl() { say( "3. <char, T> partial specialization" ); }
};
template< class T >
struct F< T, int > {
static void impl() { say( "4. <T, int> partial specialization" ); }
};
} // namespace detail
template< class T, class U >
void f() { detail::F<T, U>::impl(); }
int main() {
f<char const*, double>(); // 1
f<int, char>(); // 2
f<char, double>(); // 3
f<double, int>(); // 4
}
Well, you really can't do partial function/method specialization however you can do overloading.
template <typename T, typename U>
T fun(U pObj){...}
// acts like partial specialization <T, int> AFAIK
// (based on Modern C++ Design by Alexandrescu)
template <typename T>
T fun(int pObj){...}
It is the way but I do not know if it satisfy you.
In general, it's not recommended to specialize function templates at all, because of troubles with overloading. Here's a good article from the C/C++ Users Journal: http://www.gotw.ca/publications/mill17.htm
And it contains an honest answer to your question:
For one thing, you can't partially specialize them -- pretty much just because the language says you can't.
Since you can partially specialize classes, you can use a functor:
#include <iostream>
template <typename dtype, int k> struct fun
{
int operator()()
{
return k;
}
};
template <typename dtype> struct fun <dtype, 0>
{
int operator()()
{
return 42;
}
};
int main ( int argc , char * argv[] )
{
std::cout << fun<float, 5>()() << std::endl;
std::cout << fun<float, 0>()() << std::endl;
}