You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::bind绑定成员函数初始化timer时编译报错求助

类成员中用std::bind绑定成员函数初始化timer模板类编译失败

尝试在类成员变量中初始化接受可调用对象的timer模板实例,通过std::bind绑定类成员函数,但编译报错,代码及GCC 12.2报错信息如下:

原代码

#include <functional>
#include <type_traits>
#include <cstdio>

template <typename Callable>
struct timer
{
    template <typename = std::enable_if_t<std::is_invocable_v<Callable>, void>>
    timer(Callable func)
        : func_ {func}
    {
    }

    void invoke() const {
        func_();
    }

    Callable func_;
};

struct some_struct
{
    void do_something() {
        timer_.invoke();
    }

    void request() {
        printf("Hello\n");
    }

    const timer<decltype(std::bind(&some_struct::request, some_struct*))> timer_ { std::bind(&some_struct::request, this) };
};

int main()
{
    some_struct obj;
    obj.do_something();
}

GCC 12.2报错信息

<source>:31:70: error: expected primary-expression before '*' token
   31 |     const timer<decltype(std::bind(&some_struct::request, some_struct*))> timer_ { std::bind(&some_struct::request, this) };
      |                                                                      ^
<source>:31:71: error: expected primary-expression before ')' token
   31 |     const timer<decltype(std::bind(&some_struct::request, some_struct*))> timer_ { std::bind(&some_struct::request, this) };
      |                                                                       ^
<source>:31:73: error: template argument 1 is invalid
   31 |     const timer<decltype(std::bind(&some_struct::request, some_struct*))> timer_ { std::bind(&some_struct::request, this) };
      |                                                                         ^
<source>:31:123: error: cannot convert '<brace-enclosed initializer list>' to 'const int' in initialization
   31 |     const timer<decltype(std::bind(&some_struct::request, some_struct*))> timer_ { std::bind(&some_struct::request, this) };
      |                                                                                                                           ^
<source>: In member function 'void some_struct::do_something()':
<source>:24:16: error: request for member 'invoke' in '((some_struct*)this)->some_struct::timer_', which is of non-class type 'const int'
   24 |         timer_.invoke();
      |          

   ^~~~~~

问题分析

核心错误在timer_的类型声明中:decltype(std::bind(&some_struct::request, some_struct*))写法完全错误。std::bind的参数需要是具体的表达式(比如对象指针、实例),而some_struct*是类型,不是合法的表达式,编译器无法解析,导致模板参数无效,进而错误地将timer_推断为const int类型,引发后续一系列错误。

修复方案

方案一:改用std::function统一可调用类型

简化timer结构,使用std::function<void()>作为成员类型,无需在声明时指定bind的具体返回类型,代码更简洁:

#include <functional>
#include <cstdio>

struct timer
{
    timer(std::function<void()> func)
        : func_ {std::move(func)}
    {
    }

    void invoke() const {
        func_();
    }

    std::function<void()> func_;
};

struct some_struct
{
    void do_something() {
        timer_.invoke();
    }

    void request() {
        printf("Hello\n");
    }

    const timer timer_ { std::bind(&some_struct::request, this) };
};

int main()
{
    some_struct obj;
    obj.do_something();
}

方案二:正确推导bind的返回类型

若坚持使用模板timer,可通过std::declval生成合法的表达式来推导std::bind的返回类型,解决类未完全定义的问题:

#include <functional>
#include <type_traits>
#include <cstdio>

template <typename Callable>
struct timer
{
    template <typename = std::enable_if_t<std::is_invocable_v<Callable>, void>>
    timer(Callable func)
        : func_ {func}
    {
    }

    void invoke() const {
        func_();
    }

    Callable func_;
};

struct some_struct
{
    void do_something() {
        timer_.invoke();
    }

    void request() {
        printf("Hello\n");
    }

    // 用std::declval生成some_struct*类型的表达式,用于推导bind返回类型
    const timer<decltype(std::bind(&some_struct::request, std::declval<some_struct*>()))> timer_ { std::bind(&some_struct::request, this) };
};

int main()
{
    some_struct obj;
    obj.do_something();
}

方案对比

  • 方案一:std::function可以兼容各种可调用对象(lambda、bind、函数指针等),代码简洁,适合大多数场景,仅存在极轻微的性能开销。
  • 方案二:保留模板的类型推导,避免std::function的开销,适合对性能敏感的场景,但写法稍复杂。

内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:03:30