1

I checked This stackoverflow post, but I still cannot understand.

I have this code (yes I know <functional> achieves the same thing) which worked (if memory serves me right, it was gcc6) and now fails with gcc9.3.0

Given these class definitions

template <typename D>
class Callback{
public:
  virtual void operator()(D d)=0;
  virtual ~Callback(){}
};

template <>
class Callback <void>{
public:
  virtual void operator()()=0;
  virtual ~Callback(){}
};

and these definitions

template <typename D,typename P>
struct ParamFunctionType{
  typedef void (*value)(D,P);
};

template <typename P>
struct ParamFunctionType<void,P>{
  typedef void (*value)(P);
};

I have these subclasses

template <typename D, typename P, typename ParamFunctionType<D,P>::value f>
class FunctionParamCallback:public Callback<D>
{
    P p;

    FunctionParamCallback(const P& pp) : p(pp) {}
       
    void operator()(D d) { (*f)(d,p); }
};

template <typename P, void (*f)(P)>
class FunctionParamCallback<void, P, f> : public Callback<void>
{
    P p;

    FunctionParamCallback(const P& pp) : p(pp) {}
    void operator()() { (*f)(p); }
};

Now the second definition seems a specialization to me (for D set to void), but I get the following error

 error: partial specialization ‘class helium::scb::FunctionParamCallback<void, P, f>’ is not more specialized than [-fpermissive]
  297 |     template <typename P,void (*f)(P)> class FunctionParamCallback<void,P,f>:public Callback<void>{
      |                                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../helium/signal/callback.h:284:85: note: primary template ‘template<class D, class P, typename helium::scb::ParamFunctionType<D, P>::value f> class helium::scb::FunctionParamCallback’
  284 |     template <typename D,typename P,typename ParamFunctionType<D,P>::value f> class FunctionParamCallback:public Callback<D>{
  |                                                  

What am I mistaking?

(a MVCE is provided by Jarod42 here).

Jarod42
  • 203,559
  • 14
  • 181
  • 302
Fabio Dalla Libera
  • 1,297
  • 1
  • 10
  • 24

2 Answers2

2

This is a GCC bug filed here if I am not mistaken. It is introduced in GCC 7.1.

NutCracker
  • 11,485
  • 4
  • 44
  • 68
1

Following the reasoning of comment 4 of this bug filing provided by @NutCracker I modified the code as follows

template <typename P, typename ParamFunctionType<void, P>::value f>
class FunctionParamCallback<void, P, f> : public Callback<void>
{ /*..*/};

This prevents the possibly inconsistent resolution for the type of f, and compiles in gcc9.3 without need to relax the checks through compilation options.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
Fabio Dalla Libera
  • 1,297
  • 1
  • 10
  • 24