3

I searched the boost::hana::traits I cannot find anything related to checking concept of types. For example is_vector, is_optional. Is there any tools in hana can simplify this? Moreover, I would like to branch the code based on the result thus it needs to be used in hana::eval_if. Can anyone show me some examples?

I would like follow to work:

hana::eval_if(
    is_vector(hana::decltype_(val)),
    [&](auto _) {std::cout << "is vector\n";},
    [&](auto _) {
        hana::eval_if(
                is_optional(hana::decltype_(val)),
                [&](auto _) { std::cout << "is optional\n"; },
                [&](auto _) { std::cout << "neither vector nor optional\n"; }
        );
    }
);
Lars Br.
  • 9,949
  • 2
  • 15
  • 29
Wang
  • 7,250
  • 4
  • 35
  • 66
  • Not sure why anyone needs some third-party library, for something like that. `type_traits` has everything one needs to metaprogram a check if the given type is a `std::optional`. – Sam Varshavchik Jun 10 '20 at 20:53
  • can you kindly point me an direction? I cannot find it in https://en.cppreference.com/w/cpp/header/type_traits – Wang Jun 10 '20 at 20:55
  • You will not find it in any kind of a reference resource, but only in a good C++ textbook, that explains how to use template specializations using the type traits, for some extra help (such as `std::remove_cvref`, et. al.). – Sam Varshavchik Jun 10 '20 at 22:14

3 Answers3

4

You just sfinae that.

E.g.:

template <typename T, typename Enable = void>
struct is_optional : std::false_type {};

template <typename T>
struct is_optional<std::optional<T> > : std::true_type {};

template <typename T>
struct is_optional<boost::optional<T> > : std::true_type {};

Alternatively, you can use constexpr functions for easier use with actual variables:

Live On Coliru

#include <string>
#include <iostream>
#include <optional>
#include <boost/optional.hpp>
#include <boost/hana.hpp>
namespace hana = boost::hana;

namespace {
    template <typename T>
        constexpr bool is_optional(T const&) { return false; }
    template <typename T>
        constexpr bool is_optional(std::optional<T> const&) { return true; }
    template <typename T>
        constexpr bool is_optional(boost::optional<T> const&) { return true; }
}

template <typename T>
auto deref_opt(T const& v) {
    if constexpr(is_optional(v))
        return *v;
    else
        return v;
}

int main() {
    std::optional<double> od = 3.14;
    boost::optional<std::string> os = std::string("Pi");
    int i = 314;

#define DEMO(x) std::cout << #x << ": " << std::boolalpha << is_optional(x) << " " << deref_opt(x) << "\n";
    DEMO(i);
    DEMO(os);
    DEMO(od);
}

Prints

i: false 314
os: true Pi
od: true 3.14
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    I am aware of this: https://stackoverflow.com/a/31763111/1492613 But I am asking if there is any tools in hana which can allow me use that in hana::eval_if. – Wang Jun 10 '20 at 21:08
  • 1
    after, digging around. I guess I can wrap the is_specialization_of in to detail::hana_trait – Wang Jun 10 '20 at 21:10
  • That seems to be your ticket then. Why does it need to be hana? Before you greatly expanded your question, there was little indication that mattered (also note I expanded my answer) – sehe Jun 10 '20 at 21:15
  • I am using BOOST_HANA_ADAPT_STRUCT to loop through struct and handle the fields based on their types. – Wang Jun 10 '20 at 21:31
  • interesting your code can only compile in g++, clang9 or 10 does not work. `constexpr if condition is not a constant expression if constexpr(is_optional(v)) ^` – Wang Jun 10 '20 at 21:49
  • Oh. Yeah. Technically that's compliant I guess. It removes some of the appeal then (this would fix it https://godbolt.org/z/r5Z3dY). Nothing against the simpler class specialization though: https://godbolt.org/z/eYD2Dw – sehe Jun 10 '20 at 22:21
1

Now with concepts in c++20, the following is possible:

#include <concepts>
#include <optional>

template <typename T>
concept any_optional = std::same_as<T, std::optional<typename T::value_type>>;
szayat
  • 408
  • 3
  • 9
0

C++20 way of doing this:

template< typename T >
concept Optional = requires( T t )
{
    typename T::value_type;
    std::same_as< T, std::optional< typename T::value_type > >;
};
NutCracker
  • 11,485
  • 4
  • 44
  • 68