Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A list of lists issue #215

Open
SerhiiYashchuk opened this issue Nov 6, 2016 · 11 comments
Open

A list of lists issue #215

SerhiiYashchuk opened this issue Nov 6, 2016 · 11 comments

Comments

@SerhiiYashchuk
Copy link

SerhiiYashchuk commented Nov 6, 2016

Hi,
I'm new to metaprogramming and I've just started with brigand. I was playing with the library and faced with a problem. I can't compile the following code:

using List1 = brigand::list<int, float>;
using List2 = brigand::list<bool, char>;
using MyLists = brigand::list<List1, List2>;

int main()
{
  static_assert(brigand::index_of<MyLists, List1>() == 0, "wrong list index");
}

I get an error:

brigand/functions/lambda/apply.hpp:51: error: no type named 'type' in 'brigand::detail::apply<brigand::list<int, float>, brigand::list<brigand::list<int, float> > >'

Can you help me with this?

@nilsdeppe
Copy link
Contributor

Hi,

Here is a working example:

struct List1 {
  using type = brigand::list<int, float>;
};
struct List2 {
  using type = brigand::list<bool, char>;
};
struct List3 {
  using type = brigand::list<long, double>;
};
using MyLists = brigand::list<List1, List3, List2>;

static_assert(brigand::index_of<MyLists, List1>() == 0, "wrong list index");
static_assert(brigand::index_of<MyLists, List2>() == 2, "wrong list index");

Hope this helps. If you haven't I'd suggest going over the Boost.MPL tutorial and looking at the reference there. Generally it seems what's in MPL can be used in Brigand as well, just change the namespace.

@jonathanpoelen
Copy link
Contributor

It seems to look like a bug, algorithms work on lists, not subtypes.

brigand::index_of<MyLists, brigand::pin<List1>>

@odinthenerd
Copy link
Contributor

yes this is the cost of an unambiguous lambda syntax, since we no longer test if something is a type or a metafunction everything runs faster but as a drawback we need to pin<> everything that is meant as a type but matches template<typename...> class F

@nilsdeppe
Copy link
Contributor

It sounds like maybe the best solution is to provide this exact situation in the documentation with the brigand::pin<> solution as an example. I'm personally in favor of faster compile time, and I think with one or more examples highlighting this subtlety the current implementation would be sufficiently clear.

@SerhiiYashchuk
Copy link
Author

Thanks everyone :) Both approaches work fine.

@edouarda edouarda closed this as completed Nov 9, 2016
@edouarda edouarda reopened this Nov 9, 2016
@edouarda
Copy link
Owner

edouarda commented Nov 9, 2016

What would the example for the documentation look like?

Also, what does Marcellus Wallace look like?

@jonathanpoelen
Copy link
Contributor

@porkybrain however, remove works with a list without need to use pin. We can add pin in index_of.

template <class Sequence, class T>
using index_of = index_if<Sequence, std::is_same<pin<T>, _1>>;

@SerhiiYashchuk
Copy link
Author

By the way, the problem is in find, on which index_of relies.

@underdoeg
Copy link

underdoeg commented Nov 30, 2016

Is this also the reason why the introductory example doesn't work for me?

brigand/brigand/algorithms/detail/non_null.hpp:19:32: error: type 'bool' cannot be used prior to '::' because it has no members
struct non_null_impl : bool_<Args::value != 0>{};

#include <brigand/sequences/list.hpp>
#include <brigand/algorithms/find.hpp>
#include <type_traits>

using my_list = brigand::list<int, bool, char>;

// bool_found will be std::true_type
using bool_found = brigand::found<brigand::find<my_list, std::is_same<brigand::_1, bool>>>;

@odinthenerd
Copy link
Contributor

sorry for being swamped in work right now ;)

using my_list = brigand::list<int, bool, char>;
// no problem here, bool does not match template<typename...> pattern
using find_result = brigand::find<my_list, std::is_same<brigand::_1, bool>>;

using list_of_lists = brigand::list<brigand::list<int, int>, brigand::list<bool, bool>>;
// pin needed here, list<int,int> does match template<typename...> pattern and therefore could be a metafunction, pin says it is not a metafunction
brigand::find<list_of_lists, std::is_same<brigand::_1, list<int, int>>>;

using list_of_pairs = brigand::list<std::pair<int, int>, std::pair<bool, bool>>;
// pin needed here, pair<int,int> does match template<typename...> pattern 
brigand::find<list_of_pairs, std::is_same<brigand::_1, std::pair<int, int>>>;

using list_of_arrays = brigand::list<std::array<int, 7>, std::array<bool, 5>>;
// no problem here, std::array<bool, 5> does not match template<typename...> pattern because because 5 is not a type
brigand::find<list_of_arrays, std::is_same<brigand::_1, std::array<bool, 5>>>;

using list_of_anything = brigand::list<float,bool,char,int>;
// I can pin whatever I want, when in doubt pin everything that is 'data' as opposed to 'a metafunction'
brigand::find<list_of_anything, std::is_same<brigand::_1, brigand::pin<char>>>;

Hope this brings clarity.

@underdoeg
Copy link

underdoeg commented Nov 30, 2016

Thanks. Think I got it. But I guess my issue above is something else then?

Edit: Sorry for being way off topic. Did the implementation of brigand::found change?
This works as expected:

using my_list = brigand::list<int, bool, char>;
using bool_found = brigand::found<my_list, std::is_same<brigand::_1, brigand::pin<bool>>>;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants