GithubHelp home page GithubHelp logo

meta's People

Contributors

caseycarter avatar ericniebler avatar ghlecl avatar gnzlbg avatar kedarbhat avatar little-flower-171 avatar manu343726 avatar mpark avatar stellarpower avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

meta's Issues

Sync-up meta.cpp

... which has divergent variations in meta, range-v3, and cmcstl2.

find_indices (enhancement)

I suggest the following handy plural form of find_index:

namespace details {

        template<typename List, std::size_t I>
        struct find_ind_state {
            using L = List;
            static const std::size_t Idx = I;
        };

        template<typename Type>
        struct find_indices {
            template<typename State, typename T>
            using invoke = find_ind_state<
                                              meta::if_< std::is_same<Type,T> ,
                                                          meta::push_back< typename State::L, meta::size_t<State::Idx> >,
                                                          typename State::L
                                              >,
                                              State::Idx+1
                                          >;
        };
    };

    /** Returns a list of all indices of types equal to \p T in list \p */
    template<typename T, typename List>
    using find_indices =  typename  meta::accumulate< List,
                                                      details::find_ind_state< meta::list<> , 0 >,
                                                      /* accumulate the index list and the current index of the element*/
                                                      details::find_indices<T>
                                                      >::L;

it seems that meta::transpose does not work

using ListOfLists = meta::list< meta::list, meta::list<std::string, int>, meta::list<unsigned, long> >;

using tp_t = meta::transpose;

when the above code get compiled, the following errors are generated.

/Users/Michael_Z/open_source/meta/include/meta/meta.hpp:140:9: error: no type named 'type' in 'meta::v1::detail::fold_<meta::v1::list<meta::v1::list<char>, meta::v1::list<std::__1::basic_string<char>, int>, meta::v1::list<unsigned int, long> >, meta::v1::id<meta::v1::list<meta::v1::list<> > >, meta::v1::bind_back<meta::v1::quote<transform>, meta::v1::quote<push_back> > >' using _t = typename T::type; ^~~~~ /Users/Michael_Z/open_source/meta/include/meta/meta.hpp:1303:9: note: in instantiation of template type alias '_t' requested here using fold = _t<detail::fold_<List, id<State>, Fun>>; ^ /Users/Michael_Z/open_source/meta/include/meta/meta.hpp:2452:9: note: in instantiation of template type alias 'fold' requested here using transpose = fold<ListOfLists, ^ test_meta.cpp:12:22: note: in instantiation of template type alias 'transpose' requested here using tp_t = meta::transpose<listOfLists>; ^ 1 error generated.

anyone can figure it out ? thanks.

runtime meta::visit would be nice

I needed a runtime visitor analogue to meta::for_each:

using List = meta::list<int,double,float,double>;
std::size_t index = 2
meta::visit<List>(2, [](auto type){ std::cout << "called with type==double"; });

I came up with this, which builds a static function pointer map:

namespace meta
{
    namespace details
    {
        template<typename Func, typename Type>
        struct Wrapper
        {
            static void invoke(Func f) { f(Type{}); }
        };

        template<typename Func, typename List> struct visit;

        template<typename Func, typename... Types>
        struct visit<Func, meta::list<Types...>>
        {
            static constexpr auto makeMap()
            {
                using FuncPtr = decltype(&Wrapper<Func, void>::invoke);
                using Array   = std::array<FuncPtr, sizeof...(Types)>;
                // Build member function pointers.
                return Array{&Wrapper<Func, Types>::invoke...};
            }
        };
    }  // namespace details

    //! Apply the function `Func` with the type
    //! in the `List` at position `index`.
    template<typename List, typename Func>
    void visit(std::size_t index, Func&& f)
    {
        using F            = decltype(std::forward<Func>(f));  // Define either an lvalue, or rvalue;
        constexpr auto map = details::visit<F, List>::makeMap();
        if(index >= map.size()){ throw std::out_of_range();}
        map[index](std::forward<Func>(f));
    }

}  // namespace meta

Works like a charm for example with an rvalue lambda:

MY_TEST(MetaProgramming, Test1)
{
    using List = meta::list<int, double, short>;
    int b      = -1;
    meta::visit<List>(2,
                      [&](auto type) {
                          using T = decltype(type);
                          if constexpr(std::is_same<T, short>{})
                          {
                              b = 2;
                          }
                      });
    ASSERT_EQ(b, 2) << "Meta Visit failed!";
}

MSVC2013 support?

I know it's a long shot, since I see now newer versions use inline namespaces and constexpr, and I appreciate the desire to keep this lightweight, but it would be tremendously useful to be able to use this in VC2013 (which lacks at least those two things)

pack expansion vexations

#include <meta/meta.hpp>

struct is_positive {
    template<typename N>
    using invoke = meta::bool_<(N::type::value > 0)>;
};

using list = meta::list<
    meta::int_<1>,
    meta::int_<2>,
    meta::int_<3>,
    meta::int_<4>
>;

using result = meta::all_of<list, is_positive>;

...results in:

In file included from /Users/eniebler/Code/range-v3/scratch/scratch.cpp:5:
/Users/eniebler/Code/range-v3/include/meta/meta.hpp:560:9: error: pack expansion used as argument for non-pack parameter of alias template
        using invoke = typename F::template invoke<Args...>;
        ^~~~~

Tests do not compile with Clang 10+ because of `-Wxor-used-as-pow` (enabled by default)

FAILED: meta/test/CMakeFiles/test.meta.dir/meta.cpp.o
/usr/bin/clang++  -I/mnt/c/Users/Вова/projects/cpp-project-template/meta/include -std=c++11 -ftemplate-backtrace-limit=0 -Weverything -Werror -pedantic-errors -Wdocumentation -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-old-style-cast -Wno-documentation-unknown-command -Wno-missing-prototypes -O2 -g -DNDEBUG -fcolor-diagnostics -MD -MT meta/test/CMakeFiles/test.meta.dir/meta.cpp.o -MF meta/test/CMakeFiles/test.meta.dir/meta.cpp.o.d -o meta/test/CMakeFiles/test.meta.dir/meta.cpp.o -c '/mnt/c/Users/Вова/projects/cpp-project-template/meta/test/meta.cpp'
/mnt/c/Users/Вова/projects/cpp-project-template/meta/test/meta.cpp:1966:45: error: result of '10 ^ 15' is 5; did you mean '1e15'? [-Werror,-Wxor-used-as-pow]
        static_assert(std::is_same<int_<(10 ^ 15)>, bit_xor<int_<10>, int_<15>>>::value, "");
                                         ~~~^~~~
                                         1e15
/mnt/c/Users/Вова/projects/cpp-project-template/meta/test/meta.cpp:1966:45: note: replace expression with '0xA ^ 15' or use 'xor' instead of '^' to silence this warning
/mnt/c/Users/Вова/projects/cpp-project-template/meta/test/meta.cpp:2101:39: error: result of '10 ^ 15' is 5; did you mean '1e15'? [-Werror,-Wxor-used-as-pow]
                std::is_same<int_<(10 ^ 15)>, let<lazy::bit_xor<int_<10>, int_<15>>>>::value, "");
                                   ~~~^~~~
                                   1e15
/mnt/c/Users/Вова/projects/cpp-project-template/meta/test/meta.cpp:2101:39: note: replace expression with '0xA ^ 15' or use 'xor' instead of '^' to silence this warning
2 errors generated.

Mixing always/const_ and meta::id. Missing meta::identity Callable.

id<T>: A trait that always returns its argument T. Also, a Callable that always returns T.

Other libraries use always<T> or const_<T> for a Callable that always returns T.

Naming id<T> a Callable that doesn't behaves as the identify Callable is disturbing. I believe that id<T> should only be a trait and that we could add an meta::identity Callable

struct identity {
  template < class T>
  using invoke = T;
};

it can also be defined as

using identity = quote_trait<id>;

What do you think?

Early abortion in for_each possible?

Is there any way to support early abortion in meta::for_each (or the like).

So basically to do something at runtime for a specific Trait we can do:

int index = 2;
using A = meta::list<TraitA, TraitB , TraitC>;
meta::for_each(A{}, [](auto a){
     using Trait = decltype(a); 
     if (meta::find_index<A, Trait>  == index)
    {
          // do something ...
          return false; // abort iteration, not possible right now
    }
     return true; // true for continuation,  not possible right now
});

So far since its a aggregate initialization under the hood, this will not be possible.
Is there a better way of doing the above? With something else?

Replace meta::eval with meta::_t, add meta::_v

I've long been bothered by meta's use of eval to do something as trivial as typename T::type. I would rather use eval to evaluate deferred expressions (currently achieved by doing a let without any argument bindings, which reads a bit awkwardly IMO). Besides, since meta doesn't trade in metafunctions the way MPL does, it's wrong to encourage users to think of accessing a nested type as "evaluating" anything.

Until recently, I couldn't think of a better name for the thing eval does. But how about this:

template <typename T>
using _t = typename T::type;

template <typename T>
constexpr typename T::type::value_type _v = T::type::value;

This introduces _t as fetching a nested ::type and _v as fetching a nested ::value. These are obviously intended to evoke the xxx_t and xxx_v traits and variable templates in <type_traits>.

@gnzlbg, thoughts?

Merge variadic lambda

The code below gives meta::lambda variadic placeholders, but it's heavier weight than the existing lambda implementation. Find a way to make this lighter, or else provide both implementations and switch when a variadic placeholder is used.

template<typename T>
struct is_vararg
  : std::false_type
{};

template<typename T>
struct is_vararg<vararg<T>>
  : std::true_type
{};

template<typename A, typename T, typename F, typename Ts>
struct subst1_
  : id<list<list<T>>>
{};
template<typename T, typename F, typename Ts>
struct subst1_<F, T, F, Ts>
  : id<list<>>
{};
template<typename A, typename T, typename F, typename Ts>
struct subst1_<vararg<A>, T, F, Ts>
  : id<list<eval<Ts>>>
{};

template<typename As, typename Ts>
using substitutions_ =
    push_back<join<transform<
        concat<As, repeat_n_c<size<Ts>{} + 2 - size<As>{}, back<As>>>,
        concat<Ts, list<back<As>, back<As>>>,
        compose<quote<eval>,
            bind_back<
                quote<subst1_>,
                back<As>,
                lazy::drop<Ts, minus<size<As>, meta::size_t<2>>>>>>>, list<back<As>>>;

template<typename As>
using is_variadic = is_vararg<at<push_front<As, void>, dec<size<As>>>>;

template<typename As, typename Ts>
using substitutions =
    eval<if_c<((is_variadic<As>::value && size<Ts>::value + 2 >= size<As>::value) ||
               (size<Ts>::value + 1 == size<As>::value)), defer<substitutions_, As, Ts>>>;

template<int, typename...As>
struct lambda2_
{
private:
    template<int N, typename...Us> friend struct lambda2_;
    using Tags = list<As...>; // Includes the lambda body as the last arg!
    template<typename T, typename Args> struct impl;
    template<typename Args>
    using eval_impl = compose<quote<eval>, bind_back<quote<impl>, Args>>;
    template<template<typename...> class C, typename Args, typename Ts>
    using subst_ = apply_list<quote<C>, join<transform<Ts, eval_impl<Args>>>>;
    template<typename, typename, typename = void>
    struct impl_
    {};
    template<template<typename...> class C, typename...Ts, typename Args>
    struct impl_<defer<C, Ts...>, Args, void_<subst_<C, Args, list<Ts...>>>>
    {
        using type = list<subst_<C, Args, list<Ts...>>>;
    };
    template<typename T, typename Args>
    struct impl
      : if_<in<Tags, T>, lazy::at<Args, reverse_find_index<Tags, T>>, id<list<T>>>
    {};
    template<template<typename...> class C, typename...Ts, typename Args>
    struct impl<defer<C, Ts...>, Args> : impl_<defer<C, Ts...>, Args>
    {};
    template<template<typename...> class C, typename...Ts, typename Args>
    struct impl<C<Ts...>, Args> : impl_<defer<C, Ts...>, Args>
    {};
    template<int N, typename...Bs, typename Args>
    struct impl<lambda2_<N, Bs...>, Args>
    {
        using type = list<compose<
            typename lambda2_<0, As..., Bs...>::thunk,
            bind_front<quote<concat>, Args>,
            curry<bind_front<quote<substitutions>, list<Bs...>>>>>;
    };
    struct thunk
    {
        template<typename S, typename R = eval<impl<back<Tags>, S>>>
        using apply = if_c<size<R>{} == 1, front<R>>;
    };
public:
    template<typename...Ts>
    using apply = meta::apply<thunk, substitutions<Tags, list<Ts...>>>;
};

template<typename...As>
using lambda2 = lambda2_<0, As...>;

CI Expansion

meta's test coverage is somewhat limited (although @kedarbhat is working on adding more). range-v3 and cmcstl2 are the real meta test suite; we should incorporate them into the continuous integration testing.

Rename `list_element` to `at`

Suggestion: Rename list_element to at.
The metafunction list_element is the equivalent of at in std, such as std::vector.
list_element also contains the name of the metatype (i.e. list), which none of the other metafunctions in meta do (well except for as_list, but that doesn't count... ;-) ). I guess that this is due to simply element being a bit vague on its own.
To summarize at seems to be short, descriptive and following the std nomenclature.

Concepts and meta::lambda

There are issues in the interaction between the concept constraints in meta and the lambda implementation that need to be investigated. Concepts are applied when forming a template-id, even before instantiation, so e.g.:

template<class> concept Foo = false;
template<Foo T> struct X;
using U = X<int>; // ill-formed despite not instantiating X<int>

Yet the implementation of lambdas relies on the ability to name "invalid" specializations which are later pattern-matched and substituted into valid specializations. GCC's concept implementation is lax enough that we've been getting by with some cheating in cmcstl2, but clang-concepts (and I suspect other implementations of C++20 concepts) refuses to compile the lambda test cases in meta.cpp.

Request for interest in the equivalent of std::is_callable<Fn(Args...), R> in Meta

Hi,

I need a type traits to check if a Callable Fn can be invoked with some specific parameters Args...and if the result is convertible to a type R. Something in line with std::is_callable but using meta::invoke instead of std::invoke.

As meta::is_callable is already used what would be the name of this new type trait?

I would prefer to rename the current meta::is_callable to something else ut I don't have a good proposal. I use in my own code is_type_constructor as Meta-Callables are are functions that construct types.

  template <class, R = void>
    struct is_callable; // not defined
  template <class Fn, class ...Args, class R>
    struct is_callable<Fn(Args...), R>;
  template <class Sig, R = void> 
    constexpr bool is_callable_v = is_callable <Sig, R>::value;

If TC::template invoke<Xs...> is well formed then
if Ris void then true_type
else std::is_convertible<meta::invoke_t<Xs...>, R>
else false_type.

No conversion check is performed when R is void.

BTW, in order to avoid confusion between std Callables and meta Callables what do you think to rename Callable to Meta-Callable?

Unable to compile

Cmake works fine..

but during compilation:

/home/robotserver/meta/example/tutorial_snippets.cpp:268:5: error: static assertion failed:
static_assert(std::is_same<meta::invoke<t, unsigned>, int const &>{}, "");

Integrate self-recursive lambdas

namespace meta_detail
{
    template<typename Ts, int = 0>
    struct lambda_rec_;

    template<typename ...Ts>
    struct lambda_rec_<list<Ts...>>
    {
        template<typename...Us>
        using apply = apply<let<var<_self, lambda_rec_>, lambda<Ts...>>, Us...>;
    };
}

////////////////////////////////////////////////////////////////////////////////////
// lambda_rec
/// For defining a self-recursive lambda. In the body of a lambda, the placeholder
/// `_self` refers to the nearest enclosing `lambda_rec`
///
/// \code
/// // Define a factorial template in terms of a recursive lambda
/// using factorial_ = lambda_rec<_a,
///     lazy::if_<lazy::greater<_a, meta::size_t<0>>,
///               lazy::multiplies<_a, lazy::apply<_self, lazy::dec<_a>>>,
///               meta::size_t<1>>>;
/// template<std::size_t N>
/// using factorial = apply<factorial_, meta::size_t<N>>;
///
/// static_assert(factorial<0>::value == 1, "");
/// static_assert(factorial<1>::value == 1, "");
/// static_assert(factorial<2>::value == 2, "");
/// static_assert(factorial<3>::value == 6, "");
/// static_assert(factorial<4>::value == 24, "");
/// \endcode
template<typename ...Ts>
using lambda_rec = meta_detail::lambda_rec_<list<Ts...>>;

why use meta instead of boost::hana?

What are the benefits of using meta instead of boost::hana?

I think boost::hana can do the same and much more (glue between compile-time and run-time), and meta ist partially a nice small meta programming library (which only supports compile-time computing, except for meta::for_each) from which everything can be built on top?.

Is there some concense about that? And what do you recommend?

why does meta::for_each use a CTOR?

I am wondering why the implementation of for_each uses the CTOR in f(Args{}).
The following constructs the HugeObj just to run the lambda:

struct HugeObj
    {
        HugeObj(){ std::cout << "Huge Obj CTOR";}
    };
meta::for_each(meta::list<HugeObj>{}, [](auto&&r){});

Wouldnt it better to have a pointer

meta::for_each(meta::list<HugeObj>{}, [](auto*p){});

or a Functor f with a templated invoke<T> function
where the implementation would look like this:

return (void)std::initializer_list<int>{((void)f.invoke<Args>()), 0)...}, f;

Link is not valid

The link for 'A tiny metaprogramming library' generates 'Error establishing a database connection'.

Compilation errors with `-Werror -Wold-style-cast`

When compiling an empty program like this

#include <meta/meta.hpp>
int main() {}

The following compilation errors come from the header file:

FAILED: CMakeFiles/cpp-project-template.dir/main.cpp.o
/usr/bin/c++  -I/mnt/c/Users/Вова/projects/cpp-project-template/meta/include -O2 -g -DNDEBUG -fdiagnostics-color=always -Wall -Wextra -Wpedantic -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual -Wconversion -Wsign-conversion -Wnull-dereference -Wdouble-promotion -Wformat=2 -Werror -Wmisleading-indentation -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wuseless-cast -std=gnu++2a -MD -MT CMakeFiles/cpp-project-template.dir/main.cpp.o -MF CMakeFiles/cpp-project-template.dir/main.cpp.o.d -o CMakeFiles/cpp-project-template.dir/main.cpp.o -c '/mnt/c/Users/Вова/projects/cpp-project-template/main.cpp'
In file included from /mnt/c/Users/Вова/projects/cpp-project-template/main.cpp:1:
/mnt/c/Users/Вова/projects/cpp-project-template/meta/include/meta/meta.hpp:2657:53: error: use of old-style cast to ‘std::size_t’ {aka ‘long unsigned int’} [-Werror=old-style-cast]
 2657 |             using type = meta::size_t<((std::size_t)_v<std::is_same<T, Ts>> + ...)>;
      |                                                     ^~~~~~~~~~~~~~~~~~~~~~~
/mnt/c/Users/Вова/projects/cpp-project-template/meta/include/meta/meta.hpp:2733:80: error: use of old-style cast to ‘bool’ [-Werror=old-style-cast]
 2733 |             using type = meta::size_t<((std::size_t)(bool)invoke<Fn, L>::type::value + ...)>;
      |                                                                                ^~~~~
/mnt/c/Users/Вова/projects/cpp-project-template/meta/include/meta/meta.hpp:2733:80: error: use of old-style cast to ‘std::size_t’ {aka ‘long unsigned int’} [-Werror=old-style-cast]

Transform interface wrong?

Hi I am wondering if the interface of transform is wrong?

According to:

meta/include/meta/meta.hpp

Lines 1522 to 1523 in 9780f35

template <typename... Args>
using transform = _t<detail::transform_<list<Args...>>>;

it can only be called with arguments. But where is the fun without a Fun template?
And second, why does transform not expect a list of something like all the other meta algorithms but an unpacked list?
Right now, I am resorting to the detail implementation which seems to be the correct one.

clang 10.0 compiler error

I get a compile error with clang 10.0:

meta/meta_fwd.hpp:286:20: error: expected concept name with optional arguments
[build]         { T{} } -> typename T::value_type;
[build]                    ^

Whats the fix?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.