I'm been grinding my head against an idea that is simple enough in my head, but I can't figure out how to implement in C++.
Normally, I can declare a class with a conversion operator like in this simple example:
class Foo
{
private:
int _i;
public:
Foo( int i ) : _i(i) { }
operator int( ) const
{
return i;
}
};
So now I can write awesome stuff like
int i = Foo(3);
But in my particular case, I would like to provide an operator for converting an object to a function pointer (e.g. converting a Bar
instance to a int(*)(int, int)
function pointer). Here's what I initially tried:
class Bar
{
private:
int (*_funcPtr)(int, int);
public:
Bar( int (*funcPtr)(int, int) ) : _funcPtr(funcPtr) { }
operator int(*)(int, int) ( ) const
{
return _funcPtr;
}
};
But the operator function fails to compile, with these errors being generated:
expected identifier before '*' token
'<invalid-operator>' declared as a function returning a function
I have also tried simple variations on the above, such as surrounding the return type in parenthesis, but all these ideas have also failed.
Does anyone know what the syntax is for declaring a conversion-to-function-pointer operator method, or whether it is even possible to do so?
Note: I am compiling this with Code::Blocks using GCC 4.5.2. Answers involving some of the new C++0x concepts are also welcome.
Edit
In my strive for simplifying the example, I unintentionally left out one detail. It's a bit weird, but rather than strictly returning an int(*)(int,int)
pointer, the conversion operator is intended 开发者_运维技巧to be templated:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
// implementation is unimportant here
}
As far as I know, I no longer cannot typedef such a type. This clearly makes things much more clumsy, but I hope that there is still a way.
Since you must know:
(*operator int() const)(int, int)
{
return _funcPtr;
}
(Fixed. Again.)
Update: I've been informed by Johannes Schraub and Luc Danton that this syntax is in fact not valid, and that you really must use a typedef. Since you say that typedefs aren't an option, here's a helper class that can wrap your typedef:
template<typename R, typename A1, typename A2>
struct MakeFunctionType
{
typedef R(*type)(A1, A2);
};
template<typename R, typename A1, typename A2>
operator typename MakeFunctionType<R, A1, A2>::type () const
{
// implementation is unimportant here
}
Use a typedef. It's easier to read, anyway:
class Bar
{
public:
typedef int (*fptr_t)(int, int);
Bar(fptr_t funcPtr) : _funcPtr(funcPtr) { }
operator fptr_t() const
{
return _funcPtr;
}
private:
fptr_t _funcPtr;
};
[edit]
For your template case I do not see how to use a typedef. @Kerrik gives the (messy) version of the syntax that should work.
EDIT:
Since your class has a non template function pointer assigned at constuction:
private:
int (*_funcPtr)(int, int);
It is not at all possible to later convert that to a function pointer of any type.
I will therefore assume that you meant a template class member operator overload, not a class template member operator overload.
Template version:
template<typename ReturnType, typename ArgType1, typename ArgType2>
class Bar {
public:
typedef ReturnType (*fptr_t)(ArgType1, ArgType2);
operator fptr_t ( ArgType1 arg1, ArgType2 arg2 ) const
{
// implementation is unimportant here
}
//etc...
};
Then used like this:
//create functor to some function called myfunc
Bar::fptr_t func_ptr = Bar<int, int, int>(&myfunc);
//call functor
int i = func_ptr(1,2);
If you want to make the code readable, you need to use a typedef. I don't even use functions pointers without typedef'ing them, the syntax is too horrid.
Goal:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
return 0;
}
Path:
// 1: helper structure
template <typename R, typename A0, typename A1>
struct helper {
typedef R (*type)(A0,A1);
};
// 2: operator
template <typename R, typename A0, typename A1>
operator typename helper<R, A0, A1>::type() const {
return 0;
}
Check it out on ideone!
In C++11, it is possible to use an alias template to convert to any function, bypassing the need for custom type trait struct
s.
class Bar
{
private:
template<typename ReturnType, typename ArgType1, typename ArgType2>
using funcptr = ReturnType(*)(ArgType1, ArgType2);
public:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator funcptr<ReturnType, ArgType1, ArgType2> ( ) const;
};
To limit this to just int(*)(int, int)
, we can use SFINAE or static_assert
.
The following works in GCC:
template<typename ReturnType, typename ArgType1, typename ArgType2>
operator decltype((ReturnType(*)(ArgType1, ArgType2)) nullptr)() const
{
// ...
}
精彩评论