26

我一直在努力反对一个在我脑海中足够简单的想法,但我不知道如何在 C++ 中实现。

通常,我可以使用转换运算符声明一个类,如下面的简单示例:

class Foo
{
private:

    int _i;

public:

    Foo( int i ) : _i(i) { }

    operator int( ) const
    {
        return i;
    }
};

所以现在我可以写出很棒的东西了

int i = Foo(3);

但在我的特殊情况下,我想提供一个将对象转换为函数指针的运算符(例如,将Bar实例转换为int(*)(int, int)函数指针)。这是我最初尝试的:

class Bar
{
private:

    int (*_funcPtr)(int, int);

public:

    Bar( int (*funcPtr)(int, int) ) : _funcPtr(funcPtr) { }

    operator int(*)(int, int) ( ) const
    {
        return _funcPtr;
    }

};

但是操作符函数编译失败,产生了以下错误:

expected identifier before '*' token
'<invalid-operator>' declared as a function returning a function

我也尝试了上面的简单变体,例如将返回类型括在括号中,但所有这些想法也都失败了。

有谁知道声明转换为函数指针运算符方法的语法是什么,或者是否有可能这样做?

注意:我使用 GCC 4.5.2 使用 Code::Blocks 编译它。也欢迎涉及一些新的 C++0x 概念的答案。

编辑

在我努力简化示例的过程中,我无意中遗漏了一个细节。这有点奇怪,但不是严格地返回一个int(*)(int,int)指针,转换运算符旨在模板化:

template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
    // implementation is unimportant here
}

据我所知,我不再可以 typedef 这样的类型。这显然使事情变得更加笨拙,但我希望仍有办法。

4

6 回答 6

19

既然你必须知道:

(*operator int() const)(int, int)
{
  return _funcPtr;
}

(固定。再次。)


更新: Johannes Schraub 和 Luc Danton 告诉我,这种语法实际上是无效的,你真的必须使用 typedef。既然你说 typedefs 不是一个选项,这里有一个可以包装你的 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
}
于 2011-07-20T00:36:46.327 回答
4

使用类型定义。无论如何,它更容易阅读:

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;
};

[编辑]

对于您的模板案例,我看不到如何使用 typedef。@Kerrik 给出了应该工作的(混乱的)版本的语法。

于 2011-07-20T00:25:14.573 回答
1

编辑:

由于您的类在构造时分配了一个非模板函数指针:

private:

    int (*_funcPtr)(int, int);

以后根本不可能将其转换为任何类型的函数指针。

因此,我假设您的意思是模板类成员运算符重载,而不是类模板成员运算符重载。

模板版本:

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...

};

然后像这样使用:

//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); 
于 2011-07-20T00:39:43.417 回答
1

如果你想让代码可读,你需要使用 typedef。我什至不使用没有 typedef 的函数指针,语法太可怕了。

目标:

template<typename ReturnType, typename ArgType1, typename ArgType2>
operator ReturnType(*)(ArgType1, ArgType2) ( ) const
{
   return 0;
}

小路:

// 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;
}

ideone上查看!

于 2011-07-20T06:56:29.490 回答
1

在 C++11 中,可以使用别名模板转换为任何函数,从而绕过对自定义类型 traitstruct的需求。

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;

};

为了将其限制为仅int(*)(int, int),我们可以使用 SFINAE 或static_assert.

于 2018-08-03T18:49:05.900 回答
0

以下适用于 GCC:

template<typename ReturnType, typename ArgType1, typename ArgType2>
operator decltype((ReturnType(*)(ArgType1, ArgType2)) nullptr)() const
{
    // ...
}
于 2017-05-03T00:48:34.753 回答