Search code examples
c++c++11boostc++14fusion

boost::fusion::accumulate simple example


I have what I hope is a simple example, with a simple question someone can help clear up for me :). It's based on this other question: accumulate over tuple of values

What I have is a structure, with a std::tuple<std::string> member. During the structure's constructor, I store the data after performing some algorithms controlled by another type. Not related to my question, just explaining the code below.

What I need help with (sorry, new to boost metaprogramming!) is my toString() method that invokes boost::fusion::accumulate on the tuple I have. When I call boost::fusion::accumulate, I'm not sure how I'm supposed to be calling it! The call to boost::fusion::accumulate should be dictated by the AlgorithmT parameter.

I have the following code more or less:

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/phoenix/phoenix.hpp>

template<typename AlgorithmT, typename ...T>
struct Trait
{
  using A = AlgorithmT;

  size_t hash_value_;
  std::tuple<std::string> value_;

  Trait(T... data) :
    hash_value_(A::Hash(data...)),
    value_(A::Transform(data...)) {}
  size_t hash() const { return this->hash_value_; }

  std::string toString() const
  {
    using namespace boost::phoenix::arg_names;
    // This example compiles, but it effectively does nothing. result is always empty.
    std::string const result = boost::fusion::accumulate(this->value_, std::string{}, arg1);

    // This next line doesn't compile, but I think it's what I want.
    std::string const result = boost::fusion::accumulate(this->value_, std::string{}, &A::ToString(arg1));
    return result;
  }
};

struct IdentityAlgorithms
{
  static constexpr size_t (*Hash)(std::string const&) = &boost::hash_value;
  static constexpr auto Transform = &identity_transform<std::string>;

  static std::string ToString(std::string value) {
    std::cerr << "ToString invoked! value: '" << value << "'" << std::endl;
    return "\"" + value + "\""; }
};

Could someone look at how I am using boost::fusion::accumulate, and maybe point out how I can get the compiler to deduce the type. I'm assuming the compiler can't deduce the right type for a good reason, I'm just not sure what that is. The error messages GCC4.9 is spitting out at me is:

required from here
/local/brazil-pkg-cache/packages/Boost/Boost-3.0.3932.1/RHEL5_64/DEV.STD.PTHREAD/build/include/boost/fusion/algorithm/iteration/detail/preprocessed/fold.hpp:111:39:
error: too many arguments to function
fusion::deref(it0));


Solution

  • #include <boost/fusion/adapted/std_tuple.hpp>
    #include <boost/fusion/include/algorithm.hpp>
    #include <boost/phoenix/phoenix.hpp>
    
    template<typename AlgorithmT, typename ...T>
    struct Trait
    {
        using A = AlgorithmT;
    
        size_t hash_value_;
        std::tuple<std::string> value_;
    
        Trait(T... data) :
            hash_value_(A::Hash(data...)),
            value_(A::Transform(data...)) {}
        size_t hash() const { return this->hash_value_; }
    
        std::string toString() const
        {
            using namespace boost::phoenix::arg_names;
    
            const std::string result = boost::fusion::accumulate(this->value_, std::string{} /* initila state */, A());
            return result;
        }
    };
    
    struct IdentityAlgorithms
    {
        typedef std::string result_type;
    
        static constexpr size_t (*Hash)(std::string const&) = &boost::hash_value;
        static constexpr auto Transform = &identity_transform<std::string>;
    
        std::string operator()(const std::string& str, const std::string &value) const
                                              //  ^ state                 ^ element of squence
        {
            std::cerr << "ToString invoked! value: '" << value << "'" << std::endl;
            return "\"" + value + "\"";
        }
    };
    

    Operation static std::string ToString(std::string value) makes no sense in this case. You have to define operator().