C++ 在C+;中是否存在std::conditional的惰性等价物+;?

C++ 在C+;中是否存在std::conditional的惰性等价物+;?,c++,stl,c++17,template-meta-programming,sfinae,C++,Stl,C++17,Template Meta Programming,Sfinae,调用std::contional时,类型T1和T2都会在被调用后立即实例化,而不管bool的值如何,是否存在只实例化相关类型的实现(或实现它的一些指针) 例如,下面的代码不可能使用std::conditional编写。我们甚至不能在结构上使用SFINAE(参见示例) struct Term{}; 模板 结构成对列表 { 静态constexpr int i=N; 使用类型=T; 使用tail=PairList; }; 模板 结构成对列表 { 静态constexpr int i=N; 使用类型=T;

调用
std::contional
时,类型T1和T2都会在被调用后立即实例化,而不管bool的值如何,是否存在只实例化相关类型的实现(或实现它的一些指针)

例如,下面的代码不可能使用std::conditional编写。我们甚至不能在结构上使用SFINAE(参见示例)

struct Term{};
模板
结构成对列表
{
静态constexpr int i=N;
使用类型=T;
使用tail=PairList;
};
模板
结构成对列表
{
静态constexpr int i=N;
使用类型=T;
使用尾部=术语;
};
模板
结构获取
{
静态constexpr auto good=(N==pairList::i);
使用T=typename std::conditional<
好,,
typename pairList::type,
typename get::T>::type;//可能未定义第二个参数
};

我通常使用模板专门化来避免此类问题

// bool is false -> recursion
template <int N, typename pairList, bool = N == pairList::i>
struct get : public get<N, typename pairList::tail>
 { };

// bool is true -> stop recursion and type is selected
template <int N, typename pairList>
struct get<N, pairList, true>
 { using T = typename pairList::type; };
//bool为false->递归
模板
结构获取:公共获取
{ };
//bool为真->停止递归并选择类型
模板
结构获取
{使用T=typename pairList::type;};
下面是一个完整的编译示例

#include <type_traits>

struct Term {};

template <int N, typename T, typename ...Ts>
struct PairList
{
    static constexpr int i = N;
    using type = T;
    using tail = PairList<N + 1, Ts...>;
};

template <int N, typename T>
struct PairList<N, T>
{
    static constexpr int i = N;
    using type = T;
    using tail = Term;
};

// bool is false -> recursion
template <int N, typename pairList, bool = N == pairList::i>
struct get : public get<N, typename pairList::tail>
 { };

// bool is true -> stop recursion and type is selected
template <int N, typename pairList>
struct get<N, pairList, true>
 { using T = typename pairList::type; };


int main ()
 {
   using T0 = PairList<0u, int, long, long long>;
   using T1 = get<1u, T0>::T;

   static_assert( std::is_same_v<T1, long>, "!" );
 }
#包括
结构项{};
模板
结构成对列表
{
静态constexpr int i=N;
使用类型=T;
使用tail=PairList;
};
模板
结构成对列表
{
静态constexpr int i=N;
使用类型=T;
使用尾部=术语;
};
//bool为false->recursion
模板
结构获取:公共获取
{ };
//bool为真->停止递归并选择类型
模板
结构获取
{使用T=typename pairList::type;};
int main()
{
使用T0=成对列表;
使用T1=get::T;
静态断言(std::is_same_v,“!”);
}

您可以使用
if constexpr
惰性地实例化模板,同时保持熟悉的代码结构:

// C++20: std::type_identity
template<typename T>
struct type_t {
    using type = T;
};

template <int N, typename pairList>
struct get
{
    static auto choose_type() {
        if constexpr (N == pairList::i) {
            return type_t<typename pairList::type>{};
        } else {
            return type_t<typename get<N, typename pairList::tail>::T>{};
        }
    }

    using T = typename decltype(choose_type())::type;
};
//C++20:std::type\u标识
模板
结构类型{
使用类型=T;
};
模板
结构获取
{
静态自动选择_类型(){
if constexpr(N==pairList::i){
返回类型{};
}否则{
返回类型{};
}
}
使用T=typename decltype(选择_type())::type;
};
conditional::type
替换
conditional
// C++20: std::type_identity
template<typename T>
struct type_t {
    using type = T;
};

template <int N, typename pairList>
struct get
{
    static auto choose_type() {
        if constexpr (N == pairList::i) {
            return type_t<typename pairList::type>{};
        } else {
            return type_t<typename get<N, typename pairList::tail>::T>{};
        }
    }

    using T = typename decltype(choose_type())::type;
};