Using Boost Parameter with operator()

199 views Asked by At

I would like to use Boost Parameter together with an overloaded call operator (operator()):

#include <string>
#include <boost/parameter/keyword.hpp>
#include <boost/parameter/preprocessor.hpp>

struct add_argument_tag
{
    struct name_;
    struct descr_;
};

static inline boost::parameter::keyword<add_argument_tag::name_>&  name  = boost::parameter::keyword<add_argument_tag::name_>::get();
static inline boost::parameter::keyword<add_argument_tag::descr_>& descr = boost::parameter::keyword<add_argument_tag::descr_>::get();

struct config
{
    BOOST_PARAMETER_MEMBER_FUNCTION(
        (config),
        operator(),
        add_argument_tag,
        (required (name_, (std::string const&)))
        (optional
            (descr_, (std::string const&), "")
        )
    )
    {
        return *this;
    }
};

int main()
{
    config my_config;
    my_config
        ("foo")
        ("bar", descr = "some description");
}

Unfortunately it doesn't work:

In file included from /usr/include/boost/mpl/aux_/integral_wrapper.hpp:22,
                 from /usr/include/boost/mpl/int.hpp:20,
                 from /usr/include/boost/mpl/lambda_fwd.hpp:23,
                 from /usr/include/boost/mpl/aux_/na_spec.hpp:18,
                 from /usr/include/boost/mpl/identity.hpp:17,
                 from /usr/include/boost/parameter/aux_/unwrap_cv_reference.hpp:11,
                 from /usr/include/boost/parameter/keyword.hpp:9,
                 from /.../main.cpp:2:
/.../main.cpp:18:18: error: expected unqualified-id before ')' token
         operator(),
                  ^
/.../main.cpp:18:18: error: expected unqualified-id before ')' token
         operator(),
                  ^
/.../main.cpp:18:18: error: expected unqualified-id before ')' token
         operator(),
                  ^
/.../main.cpp:16:5: error: expected nested-name-specifier before 'boost_param_result_24operator'
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /.../main.cpp:3:
/.../main.cpp:16:5: error: expected initializer before '<' token
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/mpl/aux_/integral_wrapper.hpp:22,
                 from /usr/include/boost/mpl/int.hpp:20,
                 from /usr/include/boost/mpl/lambda_fwd.hpp:23,
                 from /usr/include/boost/mpl/aux_/na_spec.hpp:18,
                 from /usr/include/boost/mpl/identity.hpp:17,
                 from /usr/include/boost/parameter/aux_/unwrap_cv_reference.hpp:11,
                 from /usr/include/boost/parameter/keyword.hpp:9,
                 from /.../main.cpp:2:
/.../main.cpp:16:5: error: expected nested-name-specifier before 'boost_param_result_24operator'
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /.../main.cpp:3:
/.../main.cpp:16:5: error: expected initializer before '<' token
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/.../main.cpp:16:5: error: 'boost_param_default_24operator' declared as function returning a function
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/.../main.cpp:16:5: error: 'boost_param_default_24operator' declared as function returning a function
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/mpl/aux_/integral_wrapper.hpp:22,
                 from /usr/include/boost/mpl/int.hpp:20,
                 from /usr/include/boost/mpl/lambda_fwd.hpp:23,
                 from /usr/include/boost/mpl/aux_/na_spec.hpp:18,
                 from /usr/include/boost/mpl/identity.hpp:17,
                 from /usr/include/boost/parameter/aux_/unwrap_cv_reference.hpp:11,
                 from /usr/include/boost/parameter/keyword.hpp:9,
                 from /.../main.cpp:2:
/.../main.cpp:16:5: error: expected nested-name-specifier before 'boost_param_result_24operator'
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /.../main.cpp:3:
/.../main.cpp:16:5: error: expected initializer before '<' token
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/.../main.cpp:16:5: error: 'boost_param_default_24operator' declared as function returning a function
     BOOST_PARAMETER_MEMBER_FUNCTION(
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/.../main.cpp: In function 'int main()':
/.../main.cpp:34:15: error: no match for call to '(config) (const char [4])'
         ("foo")
               ^
make[3]: *** [CMakeFiles/BoostParameterProblem.dir/build.make:63: CMakeFiles/BoostParameterProblem.dir/main.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/BoostParameterProblem.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/BoostParameterProblem.dir/rule] Error 2
make: *** [Makefile:118: BoostParameterProblem] Error 2

I can easily work around this problem by having a properly named function instead of operator(), but I would really like to use operator() here... :)

I'm guessing the reason is how Boost Parameter uses macros and meta-programming to construct helper functions etc., and that using operator overloading functions are simply not possible.

Is there anyone that have made something like this work? Is it even possible?

1

There are 1 answers

0
llllllllll On BEST ANSWER

Boost Parameter does do a lot of string concatenation stuff, thus your operator() will be concatenated to an invalid name.

One way to workaround is to delegate the operator() to its implementation. Change your macro part to define a normal function, then perfect forwarding all arguments and the final result:

struct config
{
    BOOST_PARAMETER_MEMBER_FUNCTION(
        (config),
        myope,
        add_argument_tag,
        (required (name_, (std::string const&)))
        (optional
            (descr_, (std::string const&), "")
        )
    )
    {
        std::cout << name_ << " " << descr_ << "\n";
        return *this;
    }

    template<class... Args>
    decltype(auto) operator() (Args&& ...args) {
        return myope(std::forward<Args>(args)...);
    }
};

Live Demo