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;
};