2

Assuming I do not want to write a concept (or my compiler does not support them) and there is no matching type trait is there C++20 non void_t way to check if I can construct A with arguments B and C?

Note: this is a toy example, real question is is void_t still the best way beside concepts to check if something compiles in C++20.

    template <typename A, typename B, typename C,typename = void>
struct my_is_constructible : std::false_type {};
template <typename A, typename B, typename C>
struct my_is_constructible <A, B,C,
    std::void_t<decltype(A(std::declval<B>(), std::declval<C>()))>>
    : std::true_type {};
cigien
  • 57,834
  • 11
  • 73
  • 112
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 12
    This question is basically asking, "Did they add any language features to solve this problem, other than the language feature they added specifically to solve this problem?" – Nicol Bolas Oct 23 '20 at 13:45

1 Answers1

3

You can use the detected idiom, which is an abstraction over void_t. This is pretty much the closest you can get from concepts without them:

template <typename Default, typename AlwaysVoid, template<typename...> typename Op, typename... Args>
struct detector {
    using value_t = std::false_type;
    using type = Default;
};

template <typename Default, template<typename...> typename Op, typename... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
    using value_t = std::true_type;
    using type = Op<Args...>;
};

template <template<typename...> typename Op, typename... Args>
using is_detected = typename detail::detection::detector<nonesuch, void, Op, Args...>::value_t;

template <template<typename...> typename Op, typename... Args>
constexpr auto is_detected_v = detail::detection::detector<nonesuch, void, Op, Args...>::value_t::value;

template <template<typename...> typename Op, typename... Args>
using detected_t = typename detail::detection::detector<nonesuch, void, Op, Args...>::type;

template <typename Default, template<typename...> typename Op, typename... Args>
using detected_or = typename detail::detection::detector<Default, void, Op, Args...>::type;

It can then be used like this:

template<typename A, typename B, typename C>
using my_is_constructible_expr = decltype(A(std::declval<B>(), std::declval<C>()));

// Trait type that has ::value
template<typename A, typename B, typename C>
using my_is_constructible = is_detected<my_is_constructible_expr, A, B, C>;

// template variable, even closer to concepts
template<typename A, typename B, typename C>
inline constexpr bool my_is_constructible_v = is_detected_v<my_is_constructible_expr, A, B, C>;
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • Ah yes, I read something about this many years ago, but could not remember the name... too bad it is not in C++20, but then again maybe it is for best since it forces users to use 1 solution. – NoSenseEtAl Oct 23 '20 at 13:52
  • 4
    Concepts are in C++20 and are way better than the detection idiom. They are faster to compile and supports overloading properly. I don't think adding detection idiom would have worth it. – Guillaume Racicot Oct 23 '20 at 14:38