0

I'm trying to build a small C++ example using boost fusion. However, Visual Studio 2013 gives me build errors for the following piece of code. It should simply go over a associative struct and print all member names to the console:

#include <iostream>
#include <type_traits>
#include <boost/fusion/adapted/struct/define_assoc_struct.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/zip.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>

namespace keys
{
     struct name
     {};
    struct id
     {};
}

BOOST_FUSION_DEFINE_ASSOC_STRUCT((), Student,
    (std::string, name, keys::name)
    (int, id, keys::id)
);

struct getnames
{
    template<typename Sig>
    struct result;

    template <typename S, typename T>
    struct result<getnames(S, T)>
    {
        typedef std::string type;
    };

    template<class Struct, class N>
    typename result<getnames(Struct, N)>::type operator() (const N& i) const
    {
        return boost::fusion::extension::struct_member_name<Struct, i>::call();
    }
};

struct print
{
    template<typename Sig>
    struct result;

    template <typename T>
    struct result<print(T)>
    {
        typedef void type;
    };

    template<class S>
    void operator() (const S& i) const
    {
        std::cout << i << std::endl;
    };
};

int main()
{
    Student j = {"John", 42};
    auto names = boost::fusion::transform(j, getnames());
    boost::fusion::for_each(names, print());
    return 0;
}

This is my error:
boost/fusion/view/transform_view/detail/deref_impl.hpp(38): error C2039: 'type' : is not a member of 'boost::mpl::apply<boost::fusion::detail::apply_transform_result<getnames>,const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>' and four more errors which are coming up because of the first one.

To be honest, I am not an expert in the usage of boost fusion so maybe I simply missed something important here and someone else can help me.

bender
  • 613
  • 1
  • 8
  • 23

1 Answers1

1

There are several problems with your code.

1) In the Functor getnames, the signature of the result type and the signature of operator() are inconsistent (one takes one argument, the other takes two).

2) in the operator()(const N& i), i is a runtime variable. It cannot appear as a template parameter in the expression boost::fusion::extension::struct_member_name<Struct, i>.

I am not sure how to help without knowing what you want to do with getnames. Try to get to a consistent code first.

alfC
  • 14,261
  • 4
  • 67
  • 118
  • If `N` is an `integral_constant` `i` can [be used as a template parameter](http://stackoverflow.com/questions/17835689/accessing-boost-fusion-map-field-name/17842958#17842958) with clang and g++. I suspect the asker tried to copy code from somewhere and forgot an important part. – llonesmiz Mar 14 '16 at 16:48
  • I think, `i` cannot appear as a temperature parameter inside the body of the function. It is not a type, it is a variable, even if it an integer it is not a constexpr. – alfC Mar 14 '16 at 17:49
  • I'm not a language lawyer, so I don't know whether it's a bug in both [g++](http://coliru.stacked-crooked.com/a/0ad9a8a84483d66f) and [clang](http://coliru.stacked-crooked.com/a/a4cc487d70b29afe). In [Visual Studio](http://rextester.com/LPRN14803) it does not work. – llonesmiz Mar 14 '16 at 17:56
  • @cv_and_he, me neither. and you are correct, it works in `g++` and `clang` (as taken from your code http://stackoverflow.com/questions/17835689/accessing-boost-fusion-map-field-name/17842958#17842958). **I wonder what kind of magic is working on there! It is very strange to me why it works** and if it has any non-trivial application. (BTW, OP code looks very similar to yours in the linked answer) – alfC Mar 14 '16 at 18:44
  • I agree that some parts in my code are wrong. This is mainly because I didn't see or use some of the syntax in this way before (like e.g. the mentioned `struct result` which should have one argument instead of two). I will clean this up tomrrow. However, about 2): Boost tests for fusion have some examples where they often declare `template void operator()(T& t)` this or in a similar way. Thanks for the answers so far! – bender Mar 14 '16 at 20:25