小编Nic*_*teo的帖子

C++标准是否需要`#include <math.h>`来定义`<cmath>`中的`abs`重载?

C++标准在<cmath>头文件中定义了一些不属于<math.h>C中头部的重载函数(因为C没有重载).其中有float abs(float),double abs(double),long double abs(long double),和double abs(Integral).另一方面,absC <math.h>中根本没有定义(<stdlib.h>相反),唯一的签名是int abs(int).

现在在我的系统上,当使用带有C++程序的C++编译器时,#include <math.h>不会abs在全局命名空间或中提供C++ 重载std.另一方面,#include <cmath>定义std::abs.

这是我所期望的 - 包括C版本以获取C函数,并包含C++版本以获得C++函数.@visitor的回答提到了同样的事情.

但是,用户@ Cheers-and-hth-Alf坚持认为这违反了标准,因为它说"每个C头,每个都有一个表单的名称name.h,就像每个名称放在标准库名称空间中一样通过相应的cname头放在全局命名空间范围内." (本节D.5.2在C++ 03,C++ 11和C++ 14之间似乎没有太大变化.)

检查你的平台做什么很容易:看看会发生什么

#include <math.h>

int main() {
    abs(1.2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果abs未声明,<math.h>则不包括C++函数.

如果它编译,然后尝试包括<stdio.h> 并添加printf("%g\n", abs(1.2)); 如果这抱怨格式不匹配,或打印1,则<math.h> 包括C …

c++ math.h c++-standard-library

15
推荐指数
1
解决办法
5157
查看次数

将负面文字作为无符号参数传递时,g ++会发出警告吗?

考虑:

unsigned foo(unsigned u) {
    return u;
}

int main() {
    foo(-1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里,函数foo被调用u等于4294967295(或类似的大值.)如果程序员没有注意,这可能是非常意外的.

例如,您可能正在实施pow将Polynomial类提升为幂.由于只有正权力,您可以决定签名

Polynomial pow(const Polynomial& p, unsigned exp);
Run Code Online (Sandbox Code Playgroud)

然后一个粗心的程序员调用pow(p, -1)得到一个逆,而不是一个警告或错误,它似乎工作,但可能使用极大的内存和时间来产生一个完全错误的答案.

g ++ 5.3.0和gcc 5.3.0,无需投诉即可编译-Wall -Wextra.

他们将警告它的选项-Wsign-conversion,但是这发出警告每次从转换intunsigned并迅速太烦人(它警告每次指数与一个载体int,vec[i]等.)

gcc可以警告将负文字或其他负编译时常量作为无符号参数传递吗?

c c++ gcc g++ compiler-warnings

6
推荐指数
1
解决办法
213
查看次数

我说谎是一个RandomAccessIterator - 这有关系吗?

我编写了一个RandIt类(下面的代码),它的作用类似于迭代器,但只要取消引用就会返回随机整数.主要用例是使用随机数据初始化向量,如

std::vector<int> v(RandIt<0,99>{}, RandIt<0,99>{50});
Run Code Online (Sandbox Code Playgroud)

生成0到99之间的50个数字.

typedef RandIt::iterator_categorystd::random_access_iterator_tag因为

  • 它至少需要一个ForwardIterator,用于向量构造函数分配适当数量的空间来构建,用std::distance.否则emplace_back使用,重新分配和复制.
  • 它需要是RandomAccessIterator std::distance才能保持恒定时间,而不是在循环中递增和测试.

但是,这是一个谎言,因为取消引用RandIt会返回一个intby值,并且ForwardIterators和better都需要返回对内存中对象的引用.

(由于Forw​​ardIterator的"多通道保证"失败,这也可能是一个谎言:再次检查序列会产生不同的结果.但是cppreference给出了"正式"版本

表达式(void)++It(a), *a等同于表达式*a

这似乎是真的,对于某些"等价"的值.)

因此,我绝对违反了规则,声称自己不是.尽管如此,它似乎有效.

这会咬我吗?说谎的潜在影响是什么?


#include <random>
#include <iterator>

template <int min, int max>
struct RandIt {
    typedef int difference_type;
    typedef int value_type;
    typedef const int* pointer;
    typedef const int& reference;
    typedef std::random_access_iterator_tag iterator_category; // this is a lie

    static std::knuth_b rng;
    static std::uniform_int_distribution<int> idist;
    int i;

    explicit RandIt(int i = 0) : …
Run Code Online (Sandbox Code Playgroud)

c++ iterator language-lawyer

6
推荐指数
0
解决办法
124
查看次数

使用boost :: program_options禁止使用无符号值的负参数

假设我有一个程序使用boost :: program_options来解析命令行参数,并且有一个unsigned值:

#include <boost/program_options.hpp>
#include <iostream>

namespace po = boost::program_options;

int main(int argc, char* argv[]) {
    unsigned num;
    po::options_description desc;
    desc.add_options()
        ("num,n", po::value<unsigned>(&num), "Non-negative number");
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    std::cout << "Number: " << num << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后,如果我在命令行上传递一个负值,它会接受它并将其包装起来:

$ ./bponeg -n -1
Number: 4294967295

我宁愿负数会触发错误(即抛出invalid_option_value),就像我写的那样./bponeg -n abc.在解析之后,从我自己的代码中,似乎无法区分用户编写的情况-1或他们写的情况4294967295.

我可以指示program_options解析器拒绝unsigned值的负输入吗?

c++ boost boost-program-options

4
推荐指数
1
解决办法
447
查看次数

为什么我需要在临时的dynamic_bitset上调用std :: move?

我在这里讲述一个长篇大论的背景故事,因为除了直接回答之外,我想知道导致这种情况的推理是否正确.

我有一个带dynamic_bitset<>参数的函数(来自Boost.dynamic_bitset).说它看起来像这样.

void foo(boost::dynamic_bitset<> db) {
    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

碰巧它只是用构造函数构建的临时函数foo(boost::dynamic_bitset<>{5}.set())调用,如同(用5位bitset调用所有位设置).

我的位集只有少量位(少于32位).所以起初,我想"我只是按值传递它;副本比指针小." 但后来我想"它是动态的,所以它必须在堆上分配空间.我想避免不必要的分配和释放."

所以,我可以做到

void foo(const boost::dynamic_bitset<>& db);
Run Code Online (Sandbox Code Playgroud)

但是引用是一个指针,而dynamic_bitset(可能)有一个指向其数据的指针,因此使用dbwithin foo会经历两个间接级别,这看起来很愚蠢.显然,最好的方法是将指针复制到数据中foo,而无需重新分配和复制堆上的数据.

"啊哈!" 我说."当然这就是语义学的用途." 所以,我将签名更改为

void foo(boost::dynamic_bitset<>&& db);
Run Code Online (Sandbox Code Playgroud)

但是,调用foo(boost::dynamic_bitset<>{5}.set())会产生编译错误cannot bind 'boost::dynamic_bitset<>' lvalue to 'boost::dynamic_bitset<>&&'.我必须打电话 foo(std::move(boost::dynamic_bitset<>{5}.set())) 然后一切正常.

为什么我需要调用std :: move? 这似乎显然是一个xvalue(临时即将到期),不是吗?

c++ move-semantics xvalue boost-dynamic-bitset

4
推荐指数
1
解决办法
209
查看次数

将“main”包导入为库(根据_The Go 编程语言_)

在Go 编程语言的第 308 页上,它说

名为 main 的包通常会生成可执行程序,但它也可以作为库导入。

但是当我尝试时,我收到一个错误:imp.go:5:5: import "foo" is a program, not an importable package

那么……他们在说什么?如何将主包导入为库?

我的试用代码只是:

imp.go

package main

import (
    "fmt"
    "foo"
)

func main() {
    fmt.Println(foo.Hi)
}
Run Code Online (Sandbox Code Playgroud)

foo/foo.go

package main

import "fmt"

var Hi int = 3

func main() {
    fmt.Printf("Hi %d!\n", Hi)
}
Run Code Online (Sandbox Code Playgroud)

import program-entry-point package go

1
推荐指数
1
解决办法
4370
查看次数