本文介绍了将非算术类型作为参数传递给cmath函数有效吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 给定以下用户定义的类型 S ,转换函数为 double : struct S { operator double(){return 1.0;} }; 和以下对: cmath pre> #include< cmath> void test(S s){ std :: sqrt(s); std :: log(s); std :: isgreater(s,1.0); std :: isless(s,1.0); std :: isfinite(s) } 此代码使用 gcc 使用 libstdc ++ ( 观看直播 ),但是 clang 使用 libc ++ 会为几个调用产生错误> 查看实时 ),其中出现以下错误: isgreater : 错误:没有匹配的函数调用'isgreater' std :: isgreater(s,1.0); ^ ~~~~~~ 注意:候选模板被忽略:被'enable_if'禁用[with _A1 = S,_A2 = double] std :: is_arithmetic< _A1> :: value&& ^ 以及 isless 和 isfinite ,因此 libc ++ 期望这些调用的参数为算术类型其中 S 不是,我们可以通过转到 libc ++ cmath header 。尽管对于 libc ++ 中的所有 cmath 函数,算术类型的要求不一致。 所以问题是,是否将非算术类型作为参数传递给 cmath 函数?解决方案 TL; DR 根据标准,将非算术类型作为参数传递给 cmath 函数,但缺陷报告 2068 认为原始意图是 cmath 函数应该限制为算术类型,并且看起来可能使用非算术参数将最终形成不合格。因此,虽然技术上有效的使用非算术类型作为参数看起来有问题,根据缺陷报告 2068 。 详细 cath> 提供额外的 float >和 long double 重载为 math.h中定义的每个函数,其中包含 double 参数,此外, 11 p> 这似乎在C ++ 11中有效 在C ++ 11部分 26.8 [c.math]包括禁止非算术参数到 cmath 函数的任何限制。在每种情况下,从问题我们有一个重载可用的 double 参数,这些应通过 overload resolution 。 缺陷报告2086 但对于C ++ 14, href =http://cplusplus.github.io/LWG/lwg-defects.html#2086 =nofollow>缺陷报告2086:数学函数的泛型类型支持,它认为原始intent > 的目的是将 cmath 函数限制为有效仅适用于算术类型,这将模拟它们在 中的工作方式:并说:并重写了 26.8 code>段落 11 说(强调我): 所以这在C ++ 14中无效? / b> 好吧,尽管它的意图在技术上看起来仍然是有效的,如在这个评论中从 libc ++错误报告:isnan和类似函数的实现不正确: 这可能是意图,但我没有看到以这种方式读取标准的措辞。从注释#0中的示例: std :: isnan(A 没有算术类型的参数,因此 26.8 / 11中没有任何项目符号应用。重载集包含'isnan(float)','isnan(double)'和'isnan(long double)'和'isnan(float)'应该选择。 因此,第 11段的 DR 2086 改写不会使其生病形式调用 float , double 和 long double 重载,否则使用非算术参数。 技术上有效但使用起来有问题 因此,尽管C ++ 11和C ++ 14标准不限制 cmath 函数到算术参数 DR 2068 认为 26.8 paragraph 11 是限制 cmath 函数只接受算术参数,显然是为了弥补C ++中的漏洞14,但没有提供足够严格的限制。 似乎有问题的依赖于一个功能,可能会在未来版本的标准中形成不良。由于我们有实现分歧,任何依赖于将非算术参数传递给 cmath 函数的代码是非便携式的,因此只在有限的情况下有用。我们有一个替代解决方案,显式地将非算术类型转换为算术类型,这绕过了整个问题,我们不再需要担心代码变得不合格,它是可移植的: std :: isgreater(static_cast< double>(s),1.0) ^^^^^^^^^^^^^^ ^^^^^^^ As Potatoswatter指出使用一元 + 也是一个选项: std :: isgreater(+ s,1.0) 更新 在C ++ 11中指出,可以认为 26.8 段落 11 bullet 3 适用,因为参数既不是 long double ,也不是整数,因此应该是 S 应首先转换为 float 。注意,如缺陷报告 gcc 所指出的,从来没有实现这个,迄今为止我也不知道 clang 。 Given the following user-defined type S with a conversion function to double:struct S{ operator double() { return 1.0;}};and the following calls to cmath functions using the type S:#include <cmath>void test(S s) { std::sqrt(s); std::log(s); std::isgreater(s,1.0); std::isless(s,1.0); std::isfinite(s) ;}This code compiles with gcc using libstdc++ (see it live) but with clang using libc++ it generates errors for several of the calls (see it live) with the following error for isgreater:error: no matching function for call to 'isgreater' std::isgreater(s,1.0); ^~~~~~~~~~~~~~note: candidate template ignored: disabled by 'enable_if' [with _A1 = S, _A2 = double]std::is_arithmetic<_A1>::value &&^and similar errors for isless and isfinite, so libc++ expects the arguments for those calls to be arithmetic types which S is not, we can confirm this by going to the source for libc++ cmath header. Although, the requirement for arithmetic types is not consistent across all the cmath functions in libc++.So the question is, is it valid to pass non-arithmetic types as arguments to cmath functions? 解决方案 TL;DRAccording to the standard it is valid to pass non-arithmetic types as arguments to cmath functions but defect report 2068 argues the original intent was that cmath functions should be restricted to arithmetic types and it appears possible using non-arithmetic arguments will eventually be made ill-formed. So although technically valid using non-arithmetic types as arguments seems questionable in light of defect report 2068.DetailsThe cmath header is covered in the draft standard section 26.8 [c.math] provides an additional float and long double overload for the each function defined in math.h that takes a double argument and further, paragraph 11 provides for sufficient overloads and says:This seems valid in C++11In C++11 section 26.8 [c.math] does not include any restrictions disallowing non-arithmetic arguments to cmath functions. In each case from the question we have an overload available which takes double argument(s) and these should be selected via overload resolution.Defect report 2086But for C++14 we have defect report 2086: Overly generic type support for math functions, which argues that the original intent of section 26.8 [c.math] was to limit cmath functions to be valid only for arithmetic types, which would mimic how they worked in C:and says:and reworded section 26.8 paragraph 11 to say (emphasis mine):So this is invalid in C++14?Well, despite the intent it looks technically to still be valid as argued in this comment from the discussion in libc++ bug report: incorrect implementation of isnan and similar functions:So, the rewording by DR 2086 of paragraph 11 does not make it ill-formed to call the float, double and long double overloads available otherwise with non-arithmetic arguments.Technically valid but questionable to useSo although the C++11 and C++14 standard do not restrict cmath functions to arithmetic arguments DR 2068 argues the intent of 26.8 paragraph 11 was to restrict cmath functions to take only arithmetic arguments and apparently intended to close the loophole in C++14, but did not provide strong enough restrictions.It seems questionable to rely on a feature which could become ill-formed in a future version of the standard. Since we have implementation divergence any code that relies on passing non-arithmetic arguments to cmath functions for those cases is non-portable and so will be useful only in limited situations. We have an alternative solution, which is to explicitly cast non-arithmetic types to arithmetic types, which bypasses the whole issue, we no longer have to worry about the code becoming ill-formed and it is portable:std::isgreater( static_cast<double>(s) ,1.0) ^^^^^^^^^^^^^^^^^^^^^^As Potatoswatter points out using unary + is also an option:std::isgreater( +s ,1.0)UpdateAs T.C. points out in C++11 it can be argued that 26.8 paragraph 11 bullet 3 applies since the argument is neither long double, double nor an integer and should therefore the arguments of type S should be cast to float first. Note, as indicated by the defect report gcc never implemented this and as far I know neither did clang. 这篇关于将非算术类型作为参数传递给cmath函数有效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-01 22:08