gpt4 book ai didi

c++ - 在参数列表中使用std::enable_if

转载 作者:太空宇宙 更新时间:2023-11-04 16:11:53 25 4
gpt4 key购买 nike

在C ++中,请考虑以下示例:

template <typename first, typename... params> struct q;

template <typename first> struct q <first>
{
q()
{
cout<<"x"<<endl;
}
};

template <typename first, typename... params> struct q
{
q()
{
cout<<"x";
q <params...> ();
}
};

int main()
{
q <int, int> ();
q <int, int, enable_if<true, bool>::type> ();
// q <int, int, enable_if<false, bool>::type> ();
}


我定义了一个模板结构,可以接受任意数量的参数。然后,我用一组参数实例化它。每个构造函数都将构建一个新的q,除第一个参数外,其所有参数都将生成。仅带有一个参数的q将不再调用任何递归。

每次调用q的构造函数时,它将打印出一个“ x”。因此,main的第一行将导致程序打印出“ xx”,而第二行将打印出“ xxx”,因为实际上启用了enable_if。现在,如果第三行使我的程序打印出“ xx”(即:建立一个q),我将不胜感激。可悲的是,我得到的是错误

No template named 'type' in std::enable_if <false, bool>


我该怎么做才能纠正我的例子并使之生效?

谢谢

最佳答案

您误解了std::enable_if的用法。 (我们很多人都这样做了)。
这导致您提出了一个技术上错误的问题,而不是其他问题
您想回答的一般情况。您想回答的问题是我的模板如何使用或
忽略模板参数,仅基于编译时条件吗?
不好的一个。

您的印象是std::enable_if<Cond,T>::type是模板表达式
TCond时将实例化为true,而当Cond时将实例化为空
Cond为假。

truestd::enable_if<true,T>时这是正确的,因为std::enable_if<false,T>的定义如下:

std::enable_if<true,T> {
typedef T type;
};


但是 std::enable_if<false,T>::type的定义如下:

std::enable_if<false,T> {};


请参阅这些定义 here

因此 T不会消失;对于任何 type
它成为格式错误,无法编译的引用,该引用的成员类型 std::enable_if<false,T>
std::enable_if,不存在。它成为编译器错误。

因此, foo<some_bool_constant>(i)可用于实例化模板类或
根据某些函数的编译时间值,可能的函数或不可能的函数
布尔常量。并且由于编译器将忽略任何
模板的不可行实例化(如果有可行的替代方案),
因此,可以在替代项之间进行编译时选择
根据这样的条件,例如模板类或函数的实现。

template<bool Cond>
typename std::enable_if<Cond,int>::type foo(int i) // A
{
return i*i;
}

template<bool Cond>
typename std::enable_if<!Cond,int>::type foo(int i) // B
{
return i + i;
}


在这里,如果 some_bool_constanttrue并且 some_bool_constant将产生i平方
如果 falseB,我会加倍,因为在第一种情况下
A重载的格式不正确,在第二种情况下
foo<some_bool_constant>(x)重载格式不正确。

替代重载使编译器可以选择要考虑的实例化
每次看到 some_bool_constant时,其中一个结果格式不正确,而另一个则可行,
取决于 std::enable_if的真值。它选择在每种情况下都可行的一个。这个
行为称为 SFINAE,并且
是理解 std::enable_if<false,bool>::type之前需要了解的内容。

但是您没有其他实例化:

q <int, int, enable_if<false, bool>::type> ()


“取决于false的值”。无条件的错误意味着错误,所以这是错误的形式
码。

考虑:即使 std::enable_if消失了,它也会离开:

q <int, int, > ()


仍然是错误的形式。


  我该怎么做才能纠正我的例子并使之生效?


实际上,这并不需要很多,并且 q<First, ... Rest>不起作用。让我们解决一个真正的问题:我的模板如何使用或
忽略仅基于编译时条件的模板参数?

您需要以这种方式定义模板 accept_if<bool Cond, typename T>和其他模板 q
对于 Aj的任何实例化:

/*(Iq)*/    q<A0,....,Aj,....,Ak>  // 0 <= j <= k


其中 accept_if<some_bool_constant,t>::type = some_bool_constant,则如果 true == some_bool_constant
(Iq)具有与以下内容完全相同的效果:

q<A0,....,t,....,Ak>


如果 false == some_bool_constant
(Iq)将具有与以下相同的效果:

q<A0,....,Ak>


无需诉诸 accept_if<some_bool_constant,t>::type的任何运行时测试。 (在(Iq)中,
“ ....”只是可能的参数的示意图占位符:无事可做
使用C ++压缩包或省略号。)

但是 false必须在编译时解析为某种类型说明符
或代码格式错误。它无法解决。因此,在 void情况下,它必须解析为一个类型
说明符(Iq)的实例将在不指定任何数据类型的情况下进行处理。

现在,拥有不指定数据类型的类型说明符的引人注目的实用程序
C / C ++中的C语言早在很久以前就被公认为C的第一个ANSI标准。
类型说明符为 q

通过您的评论,我们了解到 void的模板参数
表示构造函数实例应提取的数据类型序列
从参数传递的来源。在这种情况下, void非常适合
作为一种类型说明符,表示什么也没做。您不能声明 accept_if对象,
更alone论从某个地方提取一个。

因此,我建议定义您的 accept_if<true,T>

template<bool Cond, typename T>
using accept_if = std::conditional<Cond,T,void>::type;


T = accept_if<false,T>void = q。阅读
std::conditional

有了这个定义,您只需要添加到您现有的专业中
q<void>个:

template<> struct q<void> {};


Aj一个默认的构造函数,不执行任何操作。这是一个示例程序
就像您自己的格式一样,说明了此解决方案:

#include <type_traits>
#include <iostream>

template<bool Cond, typename T>
using accept_if = typename std::conditional<Cond,T,void>::type;

template <typename first, typename... params> struct q;

template<> struct q<void> {};

template <typename first> struct q <first>
{
q()
{
std::cout << "x" << std::endl;
}
};

template <typename first, typename... params> struct q
{
q()
{
std::cout << "x";
q<params...>();
}
};

int main()
{
q<int, int>();
q<int, int, accept_if<true,bool>>();
q<int, int, accept_if<false,bool>>();
return 0;
}


输出是您想要的:

xx
xxx
xx


在不同的情况下,您甚至可能希望 void = struct ignore {};
在(Iq)中不容忽视。但是由于我们可以随意创建类型,因此您可以
始终创建与法定模板完全不同的法定类型
一定不要忽略,例如: 然后您将定义:

template<bool Cond, typename T>
using accept_if = std::conditional<Cond,T,ignore>::type;


并专长:

template<> struct q<ignore> {};

关于c++ - 在参数列表中使用std::enable_if,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27826029/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com