|
|
Templates and overloading problem
Hi All,
I was wondering if someone can give me assistance with the following
small program. There are two sections controlled by an #if. The
first section compiles and runs correctly (using g++), the alternative
section errors out. Both sections are attempting to do the same
thing. There is a class with a static member (wrapper) which is
overloaded based on a function template type (i.e. R func()).
I can't understand why the second section errors out. It seems like
the enable_if should be able to overload the member function types
within the same class definition.
Any help, explanations would be appreciated.
Thanks,
Oz
PS. I've provided is_void and enable_if_c which are basically like
boost's but allow simple standalone compilation of this program with
any C++ compiler.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
// is_void type trait
template <typename T> struct is_void { static const bool value =
false; };
template <> struct is_void<void> { static const bool value = true; };
// enable_if_c like boost
template <bool b, typename T> struct enable_if_c {};
template <typename T> struct enable_if_c<true, T> { typedef T type; };
// some simple functions
void foo() { std::cout << "foo\n"; }
int bar() { std::cout << "bar\n"; return 42; }
#if 1
// this works
template <typename R, typename enable = void> struct obj;
template <typename R>
struct obj<R, typename enable_if_c<is_void<R>::value, void>::type>
{
template <R func()> static void wrapper() { func(); }
};
template <typename R>
struct obj<R, typename enable_if_c<!is_void<R>::value, void>::type>
{
template <R func()> static void wrapper()
{
std::cout << "non-void: " << func() << std::endl;
}
};
#else
// this doesn't work
template <typename R>
struct obj {
template <R func()>
static typename enable_if_c<is_void<R>::value, void>::type wrapper()
{
func();
}
template <R func()>
static typename enable_if_c<!is_void<R>::value, void>::type wrapper
()
{
std::cout << "non-void: " << func() << std::endl;
}
};
#endif
int main()
{
obj<void>::wrapper<foo>();
obj<int>::wrapper<bar>();
return 0;
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
ozrictentacle1 (2)
|
1/20/2010 8:14:55 AM |
|
On 20/01/10 14:14, Oz wrote:
> Hi All,
> I was wondering if someone can give me assistance with the following
> small program. There are two sections controlled by an #if. The
> first section compiles and runs correctly (using g++), the alternative
> section errors out. Both sections are attempting to do the same
> thing. There is a class with a static member (wrapper) which is
> overloaded based on a function template type (i.e. R func()).
>
> I can't understand why the second section errors out. It seems like
> the enable_if should be able to overload the member function types
> within the same class definition.
>
> Any help, explanations would be appreciated.
>
> Thanks,
> Oz
>
> PS. I've provided is_void and enable_if_c which are basically like
> boost's but allow simple standalone compilation of this program with
> any C++ compiler.
>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
>
> #include<iostream>
>
> // is_void type trait
> template<typename T> struct is_void { static const bool value =
> false; };
> template<> struct is_void<void> { static const bool value = true; };
>
> // enable_if_c like boost
> template<bool b, typename T> struct enable_if_c {};
> template<typename T> struct enable_if_c<true, T> { typedef T type; };
>
> // some simple functions
> void foo() { std::cout<< "foo\n"; }
> int bar() { std::cout<< "bar\n"; return 42; }
>
> #if 1
>
> // this works
>
> template<typename R, typename enable = void> struct obj;
>
> template<typename R>
> struct obj<R, typename enable_if_c<is_void<R>::value, void>::type>
> {
> template<R func()> static void wrapper() { func(); }
> };
>
> template<typename R>
> struct obj<R, typename enable_if_c<!is_void<R>::value, void>::type>
> {
> template<R func()> static void wrapper()
> {
> std::cout<< "non-void: "<< func()<< std::endl;
> }
> };
>
> #else
>
> // this doesn't work
>
> template<typename R>
> struct obj {
> template<R func()>
> static typename enable_if_c<is_void<R>::value, void>::type wrapper()
> {
> func();
> }
>
> template<R func()>
> static typename enable_if_c<!is_void<R>::value, void>::type wrapper
> ()
> {
> std::cout<< "non-void: "<< func()<< std::endl;
> }
> };
This is because the return type of wrapper function does not depend on
the function deduced template argument, rather R is known at class
template instantiation time. SFINAE works at function template
instantiation time and requires deduced types of function arguments.
>
> #endif
>
> int main()
> {
> obj<void>::wrapper<foo>();
> obj<int>::wrapper<bar>();
> return 0;
> }
>
You can achieve the desired effect without SFINAE here, using only
function overloading:
[max@truth test]$ cat test.cc
#include <iostream>
// some simple functions
void foo() { std::cout << "foo"; }
int bar() { std::cout << "bar"; return 42; }
template<class T> struct Type {};
template<class R>
struct obj {
template<R func()>
static R wrapper()
{
return doWrapper<func>(Type<R>());
}
template<R func()>
static R doWrapper(Type<void>)
{
std::cout << "void: ";
func();
std::cout << '\n';
}
template<R func(), class T>
static R doWrapper(Type<T>)
{
std::cout << "non-void: ";
R r = func();
std::cout << " = " << r << '\n';
return r;
}
};
int main()
{
obj<void>::wrapper<foo>();
obj<int>::wrapper<bar>();
return 0;
}
[max@truth test]$ g++ -Wall -o test test.cc
[max@truth test]$ ./test
void: foo
non-void: bar = 42
--
Max
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Maxim
|
1/21/2010 8:14:21 PM
|
|
|
1 Replies
156 Views
(page loaded in 0.209 seconds)
|
|
|
|
|
|
|
|
|