- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这段代码有什么问题?
#include <iostream>
template<unsigned int N, unsigned int P=0>
constexpr unsigned int Log2() {
return (N <= 1) ? P : Log2<N/2,P+1>();
}
int main()
{
std::cout << "Log2(8) = " << Log2<8>() << std::endl;
return 0;
}
使用 gcc 4.6.3 版 (Ubuntu/Linaro 4.6.3-1ubuntu5)
编译时,出现以下错误:
log2.cpp: In function ‘constexpr unsigned int Log2() [with unsigned int N = 0u, unsigned int P = 1023u]’:
log2.cpp:5:38: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating ‘constexpr unsigned int Log2() [with unsigned int N = 0u, unsigned int P = 1024u]’
log2.cpp:5:38: recursively instantiated from ‘constexpr unsigned int Log2() [with unsigned int N = 4u, unsigned int P = 1u]’
log2.cpp:5:38: instantiated from ‘constexpr unsigned int Log2() [with unsigned int N = 8u, unsigned int P = 0u]’
log2.cpp:10:37: instantiated from here
最佳答案
Constexpr 不是那样工作的。
简而言之,constexpr 函数也必须作为运行时函数可用。想象一下,您从函数中删除了 constexpr。然后想想为什么它不可能工作。
原因是编译器必须完全实例化函数体;它不能根据 ?:
中的条件来决定不要实例化一侧。所以它总是要实例化递归调用,导致无限递归。
无论如何,您使用的 constexpr 是错误的。当 constexpr 打算替换它时,您正在使用旧的模板元编程计算技术(将内容作为模板参数传递)。只需使用普通参数即可。
constexpr unsigned Log2(unsigned n, unsigned p = 0) {
return (n <= 1) ? p : Log2(n / 2, p + 1);
}
std::cout << "Log2(8) = " << Log2(8) << std::endl;
编辑:我将尝试详细说明其工作原理。
当编译器遇到你的代码时,它会解析模板函数并以模板形式存储。 (编译器之间的工作方式不同。)到目前为止,一切都很好。
接下来,在 main
,编译器看到调用 Log2<8>()
.它看到它必须实例化模板,所以它继续并确实这样做:它实例化 Log2<8, 0>
.函数模板的主体是这样的:
return (N <= 1) ? P : Log2<N/2,P+1>();
好的,编译器看到了这个,但它不会尝试评估它。为什么会这样?它目前正在实例化一个模板,而不是计算一个值。它只是替换提供的值:
return (8 <= 1) ? 0 : Log2<8/2,0+1>();
咦,这里又多了一个模板实例化。它在条件表达式中或者左侧可以知道都没有关系。模板实例化必须完成。所以它继续计算新实例化的值,然后实例化 Log2<4, 1>
:
return (4 <= 1) ? 1 : Log2<4/2,1+1>();
然后游戏又开始了。那里有一个模板实例化,它是 Log2<2, 2>
:
return (2 <= 1) ? 2 : Log2<2/2,2+1>();
再一次,Log2<1,3>()
:
return (1 <= 1) ? 3 : Log2<1/2,3+1>();
我有没有提到编译器不关心这些东西的语义?这只是另一个要实例化的模板:Log2<0,4>
:
return (0 <= 1) ? 4 : Log2<0/2,4+1>();
然后 Log2<0,5>
:
return (0 <= 1) ? 5 : Log2<0/2,5+1>();
等等,等等。在某个时候,编译器意识到它永远不会停止,并放弃了。但它绝不会说:“等等,那个三元运算符的条件为假,我不需要实例化右侧。”那是因为 C++ 标准不允许这样做。函数体必须完全实例化。
现在看看我的解决方案。没有模板。只有一个功能。编译器看到它然后说,“嘿,这是一个函数。太棒了,让我在这里调用那个函数。”然后在某个时候(可能是立即,也可能是很久以后,取决于编译器),它可能(但在这种情况下不是强制的)说,“嘿,等等,这个函数是 constexpr
我知道参数值,让我评估一下。”现在它继续评估 Log2(8, 0)
.记住 body :
return (n <= 1) ? p : Log2(n / 2, p + 1);
“好的”,编译器说,“我只想知道这个函数返回什么。让我们看看,8 <= 1
是假的,所以看右边。Log2(4, 1)
,嗯?让我看看那个。好的,4 <= 1
也是错误的,所以它必须是 Log2(2, 2)
。那是什么,2 <= 1
?也是错误的,所以它是 Log2(1, 3)
。嘿,1 <= 1
是正确的,所以让我把 3
和返回它。一直到调用堆栈。”
所以它得出了答案 3。它不会进入无休止的递归,因为它是在充分了解值和语义的情况下评估函数,而不仅仅是愚蠢地构建 AST。
希望对您有所帮助。
关于C++11 constexpr 函数编译器错误与三元条件运算符 (? :),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18231591/
我想知道javascript中if的简码是什么? 就像在 PHP 中一样: $res = ($x > $y)? $x: $y; 它在 JavaScript 中的转换是什么? 最佳答案 在 javasc
请问为什么下面的代码会报错? 错误: numberOne > numberTwo ? return "true" : return "false"; ^
在我的代码中,我检查系统函数是否等于零,如果是我返回另一个值,如果不是,我返回测试值。 (class.verylongfunc(arg, arg) == 0) ? othervar : cla
在 PHP 中,有没有一种方法可以使用三元条件连接两个字符串? 当我尝试这样做时,我得到的只是 else 而不是所需的 something else。 最佳答案 像这样把整个三元运算符放在方括号中:
似乎在三元运算符中存在某种类型混淆。我知道这已在其他 SO 线程中得到解决,但它始终与可空值有关。另外,就我而言,我真的只是在寻找更好的方法。 我希望能够使用 proc.Parameters[PARA
有没有办法在不进行赋值或伪造赋值的情况下进行 java 三元运算? 我喜欢在执行一堆 if/then/else 时的简洁三元代码。 我希望能够基于 boolean 代数语句调用两个 void 函数之一
我正在使用 XSLT 和 XML 来生成输出文档。 我在数据中拥有的(以我无法控制的 XML 形式)如下: 4 我需要在计算中使用这些。我看到为这些提供默认值需要对文档执行转换以提供一个有点冗长的
这个问题已经有答案了: Ternary operators in JavaScript without an "else" (13 个回答) 已关闭 4 年前。 我一直使用这样的三元表达式,但我不喜欢
我在 VB.NET 中发现了一个可以轻松重现的简单错误: Dim pDate As Date? Dim pString As String = "" ' works fine as expected
所以,我有这段代码,它实际上有效: (散列将是这样的对象:{"bob"=> "12, "Roger"=> "15", etc},并且 isGood(key) 是调用函数 isGood ,如果玩家好或坏
是否有以下 JavaScript bool 三元表达式的简写语法: var foo = (expression) ? true : false 最佳答案 当然,您只想将表达式转换为 bool 值: v
在 Java 中,如果我在常规 if 中使用三元 if 运算符,例如: if ((x > y - z) ? true : callLongWaitedMethod(many, parameteres)
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 7 年前。 Improve
var test = "Hello World!"; 在 Java 10+ 中,上面的代码片段可以编译,test 在编译时被推断为 String。 但是,我们可以使用条件(三元)运算符来返回不同的类型
嗨,我尝试在渲染内部使用三元条件,但遇到一些错误,这是我的代码: render() { return ( (this.emai
这里我有以下 JavaScript 代码,带有两个值。 var w = $("#id1").val(); var h = $("#id2").val(); (w == h) ? (w=350 , h
我一直想知道如何用 C++ 兼容语言编写 "A ? B : C" 语法。 我认为它的工作方式类似于:(伪代码) If A > B C = A Else C = B 有没有经验丰富的 C++
考虑两个 vector ,A 和 B,大小为 n,7 <= n <= 23 . A 和B 都只包含-1、0 和1。 我需要一个计算A 和B 内积的快速算法。 到目前为止,我一直在考虑使用以下编码将
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
如果您一开始就讨厌三元条件运算符,则无需回复 ;) 我经常看到它与赋值表达式一起使用,例如: var foo = (some_condition) ? then_code : else_code; 但
我是一名优秀的程序员,十分优秀!