Universal and existential quantification using the C ++ template template

Is there a way to implement universal and existential using C ++ template magic (possibly using SFINAE, etc.)? Something like that:

template
    <
        template <typename Argument> class Predicate
    >
struct UniversalQuantification
{
    static const bool value =
        /*for any Argument Predicate<Argument>::value == true ? true : false*/;
};

template
    <
        template <typename Argument> class Predicate
    >
struct ExistentialQuantification
{
    static const bool value =
        /*for some Argument Predicate<Argument>::value == true ? true : false*/;
};
+4
source share
4 answers

If you pass the template to the final template of the possible templates, it is really possible to evaluate at compile time. However, it is not possible to evaluate this for each argument with which the past pattern was used, since these / args types are unknown.

ExistentialQuantification. UniversalQuantification, || &&:

template<typename Arg>
struct Pred1;

template<>
struct Pred1<float> { static const bool value = true; };

template<>
struct Pred1<double> { static const bool value = false; };

template<>
struct Pred1<long> { static const bool value = true; };


template<template <typename Argument> class Predicate, typename... Types>
struct ExistentialQuantification;

template<template <typename Argument> class Predicate, typename Arg>
struct ExistentialQuantification<Predicate, Arg>
{
    static const bool value = Predicate<Arg>::value;
};

template<template <typename Argument> class Predicate, typename Arg, typename... Types>
struct ExistentialQuantification<Predicate, Arg, Types...>
{
    static const bool value = Predicate<Arg>::value || ExistentialQuantification<Predicate, Types...>::value;
};

int main()
{
    std::cout << ExistentialQuantification<Pred1, long, double, float>::value << std::endl;
}

value true || false || true , , .

+3

, , , , , .

  • , , :

    template<typename> struct always : std::true_type { };

  • , , :

    template<typename> struct never : std::false_type { };

:

template<template<typename> class>
struct UniversalQuantification : std::false_type { };

template<>
struct UniversalQuantification<always> : std::true_type { };

template<template<typename> class>
struct ExistentialQuantification : std::true_type { };

template<>
struct ExistentialQuantification<never> : std::false_type { };
+3

Boost.MPL, , boost::mpl::vector, std::all_of std::any_of . :

#include <ios>
#include <iostream>
#include <type_traits>                  // is_same, is_base_of
#include <boost/mpl/end.hpp>            // end
#include <boost/mpl/find_if.hpp>        // find_if
#include <boost/mpl/lambda.hpp>         // lambda
#include <boost/mpl/logical.hpp>        // not_
#include <boost/mpl/placeholders.hpp>   // _1
#include <boost/mpl/vector.hpp>         // vector

template<typename Sequence, typename Pred>
struct all_of
:
        std::is_same< typename
                boost::mpl::find_if<
                        Sequence,
                        boost::mpl::not_<Pred>
                >::type, typename
                boost::mpl::end<Sequence>::type
        >
{};

template<typename Sequence, typename Pred>
struct none_of
:
        all_of< Sequence, boost::mpl::not_< Pred > >
{};

template<typename Sequence, typename Pred>
struct any_of
:
        boost::mpl::not_< none_of< Sequence, Pred > >
{};

struct B {}; 
struct D : B {};
struct X {};

using Universe = boost::mpl::vector<B, D, X>;
using Predicate = boost::mpl::lambda<std::is_base_of<B, boost::mpl::_1>>;

int main()
{
    std::cout << std::boolalpha;
    std::cout << all_of<Universe, Predicate>{} << "\n";
    std::cout << any_of<Universe, Predicate>{} << "\n";
}

.

, X B , , D B , .

+1

Well, if we just talk about n-ary (variable) functions and , or , as in the answer of TemplateRex , here is my preferred way without Boost:

using _true  = std::integral_constant <bool, true>;
using _false = std::integral_constant <bool, false>;

template <bool C, typename T, typename E>
using _if = typename std::conditional <C, T, E>::type;

template <typename...> struct _and;
template <typename...> struct _or;

template <typename A, typename... B>
struct _and <A, B...> : _if <A{}, _and <B...>, _false> { };

template <typename A, typename... B>
struct _or <A, B...> : _if <A{}, _true, _or <B...> > { };

template <> struct _and <> : _true { };
template <> struct _or <> : _false { };
+1
source

Source: https://habr.com/ru/post/1533386/


All Articles