代码之家  ›  专栏  ›  技术社区  ›  jpihl

带有默认std::function参数的模板化函数导致已定义符号[…]

  •  5
  • jpihl  · 技术社区  · 8 年前

    我只是遇到了一些奇怪的事情。 我想知道这是不是一个错误,如果不是,我希望有人能解释这个问题。

    std::function 作为默认参数,我只能创建这个函数的一个模板实例化,否则会出错。

    #include <functional>
    
    template<bool B>
    void wut(std::function<void()> f = []() {})
    {
        f();
    }
    
    int main() {
        wut<false>(); // works
        wut<false>(); // still works
        wut<true>();  // error
        return 0;
    }
    

    https://ideone.com/VlVcUv

    {standard input}: Assembler messages:
    {standard input}:28: Error: symbol `_ZNSt14_Function_base13_Base_managerIUlvE_E10_M_managerERSt9_Any_dataRKS3_St18_Manager_operation' is already defined
    {standard input}:127: Error: symbol `_ZNSt17_Function_handlerIFbvEUlvE_E9_M_invokeERKSt9_Any_data' is already defined
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   Shafik Yaghmour    8 年前

    这是一个gcc错误(在版本7.3之后看起来已经修复了),我们可以通过查看第节来了解这一点 [expr.prim.lambda.capture]p9 :

    void f2() {
    int i = 1;
    void g1(int = ([i]{ return i; })()); // ill-formed
    void g2(int = ([i]{ return 0; })()); // ill-formed
    void g3(int = ([=]{ return i; })()); // ill-formed
    void g4(int = ([=]{ return 0; })()); // OK
    void g5(int = ([]{ return sizeof i; })()); // OK
    }
    

    [结束示例]

    your example live there .

        2
  •  0
  •   Quentin    8 年前

    然而,在头文件中使用lambda充满了ODR问题。所以我会避开它。

    template<auto X>
    struct always_return {
      template<class...Args>
      auto operator()(Args&&...)const{ return X; }
    };
    
    template<bool B>
    void wut(std::function<bool()> f = always_return<false>{})
    {
    

    :

    template<class T>
    struct always_return_t {
      T t;
      template<class...Args>
      auto operator()(Args&&...)const{ return t; }
    };
    template<class T>
    always_return_t<typename std::decay<T>::type> always_return(T&&t) {
      return {std::forward<T>(t)};
    }
    template<bool B>
    void wut(std::function<bool()> f = always_return(false)){
    
    推荐文章