functional.hpp 1.56 KB
Newer Older
1
#pragma once
Chao Liu's avatar
Chao Liu committed
2
3
#include "integral_constant.hpp"
#include "Sequence.hpp"
4

Chao Liu's avatar
Chao Liu committed
5
6
7
struct forwarder
{
    template <typename T>
Chao Liu's avatar
Chao Liu committed
8
    __host__ __device__ constexpr T&& operator()(T&& x) const
Chao Liu's avatar
Chao Liu committed
9
    {
Chao Liu's avatar
Chao Liu committed
10
        return static_cast<T&&>(x);
Chao Liu's avatar
Chao Liu committed
11
12
13
    }
};

Chao Liu's avatar
Chao Liu committed
14
15
16
17
18
19
20
21
struct swallow
{
    template <class... Ts>
    __host__ __device__ constexpr swallow(Ts&&... ts)
    {
    }
};

Chao Liu's avatar
Chao Liu committed
22
// Emulate if constexpr
Chao Liu's avatar
Chao Liu committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
template <bool Predicate>
struct static_if
{
};

template <>
struct static_if<true>
{
    using Type = static_if<true>;

    template <class F>
    __host__ __device__ constexpr auto operator()(F f) const
    {
        // This is a trick for compiler:
        //   Pass forwarder to lambda "f" as "auto" argument, and maks sure "f" will use it,
Chao Liu's avatar
Chao Liu committed
38
39
        //   this will make "f" a generic lambda, so that "f" won't be compiled until being
        //   instantiated here
Chao Liu's avatar
Chao Liu committed
40
41
42
43
44
        f(forwarder{});
        return Type{};
    }

    template <class F>
45
    __host__ __device__ static constexpr auto Else(F)
Chao Liu's avatar
Chao Liu committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    {
        return Type{};
    }
};

template <>
struct static_if<false>
{
    using Type = static_if<false>;

    template <class F>
    __host__ __device__ constexpr auto operator()(F) const
    {
        return Type{};
    }

    template <class F>
63
    __host__ __device__ static constexpr auto Else(F f)
Chao Liu's avatar
Chao Liu committed
64
65
66
    {
        // This is a trick for compiler:
        //   Pass forwarder to lambda "f" as "auto" argument, and maks sure "f" will use it,
Chao Liu's avatar
Chao Liu committed
67
68
        //   this will make "f" a generic lambda, so that "f" won't be compiled until being
        //   instantiated here
Chao Liu's avatar
Chao Liu committed
69
70
71
72
        f(forwarder{});
        return Type{};
    }
};