#ifndef CK_FUNCTIONAL_HPP #define CK_FUNCTIONAL_HPP #include "integral_constant.hpp" #include "sequence.hpp" #include "type.hpp" namespace ck { // TODO: right? wrong? struct forwarder { template __host__ __device__ constexpr T&& operator()(T&& x) const { return static_cast(x); } }; struct swallow { template __host__ __device__ constexpr swallow(Ts&&...) { } }; // Emulate if constexpr template struct static_if; template <> struct static_if { using Type = static_if; template __host__ __device__ constexpr auto operator()(F f) const { // This is a trick for compiler: // Pass forwarder to lambda "f" as "auto" argument, and make sure "f" will use it, // this will make "f" a generic lambda, so that "f" won't be compiled until being // instantiated here f(forwarder{}); return Type{}; } template __host__ __device__ static constexpr auto Else(F) { return Type{}; } }; template <> struct static_if { using Type = static_if; template __host__ __device__ constexpr auto operator()(F) const { return Type{}; } template __host__ __device__ static constexpr auto Else(F f) { // This is a trick for compiler: // Pass forwarder to lambda "f" as "auto" argument, and make sure "f" will use it, // this will make "f" a generic lambda, so that "f" won't be compiled until being // instantiated here f(forwarder{}); return Type{}; } }; template struct conditional; template struct conditional { using type = X; }; template struct conditional { using type = Y; }; template using conditional_t = typename conditional::type; } // namespace ck #endif