Home > Back-end >  Problem when trying to obtain an std::reference_wrapper with a particular template class parameter
Problem when trying to obtain an std::reference_wrapper with a particular template class parameter

Time:01-28

I am struggling with a problem that I am not able to solve. I searched all around the website and web in general and didn't find any solution (maybe this is due to the fact that I doesn't understand well something and I am not able to ask it correctly).

The problem is the following, supposing I have a template class with some parameters, whose one of them is a tempate itself, defined in a class.h file:

template <template <typename bar_type> typename Indicator, size_t count>
class MultiProgressBar
 {
  public:

   template <typename... Indicators, typename = typename std::enable_if_t <(sizeof...( Indicators ) == count )>>
   explicit MultiProgressBar( Indicators &... bars ) : bars_( { bars... } ) {}
 
  private:
   
   std::array <std::reference_wrapper<Indicator>, count> bars_;
 };

In my main.cpp file I want to be able to do something like this:

ProgressBar<int> prog_int;
ProgressBar<double> prog_double;
ProgressBar<float> prog_float;

MultiProgressBar <ProgressBar, 3> bars( prog_int, prog_double, prog_float );

where ProgressBar is a template class defined in another header called for example progress.h

The problem is that when I compile, I got this error (I don't post the whole makefile since it would be really complex and long to explain, however let's take into account that I am compiling more stuff, but the only significant one for this error is given in this post):

g   -g -Isrc -MMD -MP  -c src/main.cpp -o obj/src/main.cpp.o
In file included from src/../include/osmanip.h:7,
                 from src/main.cpp:6:
src/../include/multi_progress_bar.h:48:50: error: type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp> class std::reference_wrapper’
   48 |      std::array <std::reference_wrapper<Indicator>, count> bars_;
      |                                                  ^
src/../include/multi_progress_bar.h:48:50: note:   expected a type, got ‘Indicator’
src/../include/multi_progress_bar.h:48:58: error: template argument 1 is invalid
   48 |      std::array <std::reference_wrapper<Indicator>, count> bars_;
      |                                                          ^
src/../include/multi_progress_bar.h: In instantiation of ‘osm::MultiProgressBar<Indicator, count>::MultiProgressBar(Indicators& ...) [with Indicators = {osm::ProgressBar<int>, osm::ProgressBar<double>, osm::ProgressBar<float>}; <template-parameter-2-2> = void; Indicator = osm::ProgressBar; long unsigned int count = 3]’:
src/main.cpp:245:77:   required from here
src/../include/multi_progress_bar.h:23:77: warning: list-initializer for non-class type must not be parenthesized
   23 |      explicit MultiProgressBar( Indicators &... bars ) : bars_( { bars... } ) {}
      |                                                                             ^
src/../include/multi_progress_bar.h:23:77: error: cannot convert ‘<brace-enclosed initializer list>’ to ‘int’ in initialization
make: *** [makefile:65: obj/src/main.cpp.o] Error 1

Do you know what could be wrong with my code?

CodePudding user response:

You'll need a common base for the elements you store references too. This could be one way:

struct ProgressBarBase {
    // Optional: A virtual destructor if you want to delete objects via
    // base class pointers:
    virtual ~ProgressBarBase() = default;
};

template <class T>
struct ProgressBar : public ProgressBarBase {};

With that, you could change your class slightly to store references to ProgressBarBase (or whatever indicator base class you'd like).

template <class T, std::size_t count>
class MultiProgressBar {
public:
    template<class... Indicators, std::enable_if_t<sizeof...(Indicators) == count, int> = 0>
    MultiProgressBar(Indicators&&... bars)
        : bars_{std::forward<Indicators>(bars)...}
    {
        // or this instead of SFINAE:
        static_assert(sizeof...(Indicators) == count, "wrong number of arguments");
    }

private:
    std::array<std::reference_wrapper<T>, count> bars_;
};

int main() {
    ProgressBar<int> prog_int;
    ProgressBar<double> prog_double;
    ProgressBar<float> prog_float;

    MultiProgressBar<ProgressBarBase, 3> bars(prog_int, prog_double, prog_float);
}
  •  Tags:  
  • Related