0

I am having trouble compiling a class header which contains a member field of type sregex.

The class is defined as :

#include <boost/xpressive/xpressive_fwd.hpp>
namespace Bob
{

class RegexReplace
{
public :
    boost::xpressive::sregex m_rx;
    std::string m_str;

    RegexReplace(const char* strSearch, const char* strReplace);
};

} // namespace Bob

The class cpp file compiles without any problem, but when I include the header into a cpp file which uses the class, the compiler gives the following error :

error: field ‘m_rx’ has incomplete type ‘boost::xpressive::sregex’ {aka ‘boost::xpressive::basic_regex<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >’}
boost::xpressive::sregex m_rx;

What am I doing wrong here ???

Simon
  • 2,208
  • 4
  • 32
  • 47
  • 1
    The name `xpressive_fwd` probably means that header contains forward declarations only. So you include the wrong header, most likely. – StoryTeller - Unslander Monica Mar 11 '19 at 08:16
  • This is indeed the header for forward declarations, which I understood was supposed to be used in precisely this case - a header file to be included in other files. It is supposed to avoid the need of all other full definitions. Or have I missed something here ? – Simon Mar 11 '19 at 08:42
  • Forward declarations are for "hey, there is a type here which I will define later". If you want to forward declare your regex you'll have to change it to a pointer. Then include xpressive.hpp in the cpp file (to define it) and allocate dynamically. – Niclas Larsson Mar 11 '19 at 08:49
  • I am using `xpressive_static.hpp` for static and not dynamic regex. I would quite happily create the sregex dynamically (as a pointer to static definition), but I do not see how to do this - not as simple as `new sregex(...)`. Any advice ? – Simon Mar 11 '19 at 08:54
  • I would stick to stack memory, it's faster and the code would be less error prone. – Niclas Larsson Mar 11 '19 at 09:04
  • Any reason why you dont just remove `_fwd` from the header and assign `m_rx{sregex::compile(strSearch)}` in the initializer list? – Niclas Larsson Mar 11 '19 at 09:11
  • Which means that I am obliged to include `xpressive_static.hpp`, that's a disappointing. I was hoping to have a header as light as possible. – Simon Mar 11 '19 at 09:12
  • Because I do not use sregex::compile - only static definitions – Simon Mar 11 '19 at 09:13
  • Trying to cut down compilation times? You can use precompiled headers for that (or go the pointer route). – Niclas Larsson Mar 11 '19 at 09:13

1 Answers1

0

boost::xpressive::sregex m_rx; is a instantiation and you only forward declared it by including ..._fwd.hpp, in other words it's incomplete.

#include <boost/xpressive/xpressive.hpp> should solve the issue.

If you really want to forward declare your type you'll have to change it to a pointer (non working code, looks like boost uses a static ::compile(...)):

hpp:

#include <boost/xpressive/xpressive_fwd.hpp>
namespace Bob
{

class RegexReplace
{
public :
    boost::xpressive::sregex* m_rx;
    std::string m_str;

    RegexReplace(const char* strSearch, const char* strReplace);
    ~RegexReplace();

    // @todo Implement move and copy semantics
};

} // namespace Bob

cpp:

#include <boost/xpressive/xpressive.hpp>
namespace Bob
{
  RegexReplace::RegexReplace(const char* strSearch, const char* strReplace) :
    m_rx{new boost::xpressive::sregex}
  {
    ......
  }

  RegexReplace::~RegexReplace() {
    delete m_rx;
  }
}
Niclas Larsson
  • 1,317
  • 8
  • 13