Class with non-static lambda member can't use

2019-06-26 09:06发布

问题:

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

回答1:

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.



回答2:

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