Class with non-static lambda member can't use

2019-06-26 08:30发布

This small test program:

#include <functional>

//template<class T>            // <-- with this, gcc compiles  ok
template<class T=void>
struct  c{
        std::function<int(int)> f = [](int i){return i+i;};
};

int main() {};

Clang-3.2 compiles it ok, but from GCC 4.7.1 and 4.8 I am getting strange error:

t.cc:6:31: error: default argument for template parameter for class enclosing ‘struct __lambda0’
  function<int(int)> f = [](int i){return i+i;};
                               ^

Is this one of those obscure C++ rules exceptions that nobody knows about or is it a GCC bug?

EDIT Looks like a bug. I've filed bug report

2条回答
唯我独甜
2楼-- · 2019-06-26 08:59

This code will get error anyway on gcc. Yes, without default argument it can be compiled. It can be compiled because struct c isn't used anywhere. But if you try to create instance of this struct, you will get error.

#include <functional>

template<class T>
struct c {
    std::function<int(int)> f = [](int i){return i+i;};
};

int main() {
    c<int> _c; // error
}

It looks like a bug of gcc. This way can help to avoid problem.

#include <functional>
#include <iostream>

template<class T=void>
struct c {
   c() : f([](int i){return i+i;}) {
   }

   std::function<int(int)> f;
};

int main() {
   c<> _c; 
   std::cout << _c.f(10) << std::endl;
}
查看更多
smile是对你的礼貌
3楼-- · 2019-06-26 09:11

I think this is a g++ bug with default member initialization. I'm not positive about this, and so have the following supporting evidence:

template<class T=void>
struct  c {
   std::function<int(int)> f;
   c() : f([](int i){return i+i;}) {
   }
};

int main() {}

If that works, what you're doing should work too. And it does, even if you construct a c.

Personally, I think default member initialization should be used sparingly and with care. I think it's really easy to create a lot of confusion with it because most people expect all the initialization to be done in the constructor, and member initializers are not necessarily anywhere near any constructor. So they can leave someone scratching their head wondering how some member gets a particular value.

I can see cases, especially with simple, mostly-data classes for which it would work pretty well. But mostly, I think if you have a constructor body of any kind, you should probably not be using default member initialization.

查看更多
登录 后发表回答