小编Bia*_*sta的帖子

函数中的r值参数

当在函数之间传递r值时,我想知道c ++行为.

看看这个简单的代码:

#include <string>

void foo(std::string&& str) {
  // Accept a rvalue of str
}

void bar(std::string&& str) {
  // foo(str);          // Does not compile. Compiler says cannot bind lvalue into rvalue.
  foo(std::move(str));  // It feels like a re-casting into a r-value?
}

int main(int argc, char *argv[]) {
  bar(std::string("c++_rvalue"));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我知道当我在bar函数内部时我需要使用move函数来调用foo函数.我现在的问题是为什么?

当我在bar函数内部时,变量str应该已经是一个r值,但编译器就像是一个l值.

有人可以引用一些关于这种行为的标准吗?谢谢!

c++ rvalue c++11

18
推荐指数
3
解决办法
3552
查看次数

表达副作用的Clang警告

给出以下源代码:

#include <memory>
#include <typeinfo>

struct Base {
  virtual ~Base();
};

struct Derived : Base { };

int main() {
  std::unique_ptr<Base> ptr_foo = std::make_unique<Derived>();

  typeid(*ptr_foo).name();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

并编译它:

clang++ -std=c++14 -Wall -Wextra -Werror -Wpedantic -g -o test test.cpp

环境设置:

linux x86_64
clang version 5.0.0
Run Code Online (Sandbox Code Playgroud)

由于警告(注释-Werror)它不编译:

error: expression with side effects will be evaluated
      despite being used as an operand to 'typeid'
      [-Werror,-Wpotentially-evaluated-expression]
  typeid(*ptr_foo).name();
Run Code Online (Sandbox Code Playgroud)

(请注意:海湾合作委员会并未声称存在这种潜在问题)


有没有办法获得有关a指向的类型的信息unique_ptr而不产生那种警告?

注意:我不是在谈论禁用-Wpotentially-evaluated-expression或避免-Werror.

c++ typeid clang++

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

在const上的结构化绑定

以下代码应该编译吗?

#include <type_traits>

void foo() {
  const std::pair<int, int> x = {1, 2};

  auto [a, b] = x;

  static_assert(std::is_const_v<decltype(a)>);
  static_assert(std::is_const_v<decltype(b)>);
}
Run Code Online (Sandbox Code Playgroud)

那么,这是MSVC错误吗?

该标准是不是直接在这里(我有一个快速浏览一下),但考虑规则auto,我想,a并且b应该被复制丢弃CV-预选赛

c++ c++17 structured-bindings

11
推荐指数
2
解决办法
370
查看次数

在fstream open上不处理异常

上下文

我有这个简单的代码:

#include <iostream>
#include <fstream>
#include <system_error>

int main(int argc, char *argv[]) {
  std::ifstream file;
  file.exceptions(std::ios::failbit | std::ios::badbit);

  try {
    file.open("a_file_does_not_exist.txt", std::ios::in);
    file.close();
  } catch(const std::ios_base::failure& err) {
    std::cerr << err.code() << std::endl;
    return -1;
  }

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

刚刚完成,这是编译命令:

 g++ -std=c++11 -g //  ...
Run Code Online (Sandbox Code Playgroud)

编译器的版本是g ++(GCC)6.1.1.

平台:arch-linux 4.7.2-1.


问题

可以想象,该文件不存在,因此该方法file.open(...)将引发异常.问题是,当我运行代码的异常没有被处理,而std::terminate被调用.

奇怪的是输出:

terminate called after throwing an instance of 'std::ios_base::failure'
  what():  basic_ios::clear
Annullato (core dump creato)
Run Code Online (Sandbox Code Playgroud)

正如你所读到的那样,投掷课是一个std::ios_base::failure,但我的抓住是正确的. …

c++ exception-handling c++11 system-error

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

C++编译器中的可变长度数组(VLA)

我们已经知道,VLA(在C99中标准化)不是C++标准的一部分.

所以下面的代码在C++中是"非法的":

void foo(int n) {
  int vla[n];
  for (int i = 0; i < n; ++i) {
    vla[i] = i;
  }
}
Run Code Online (Sandbox Code Playgroud)

尽管编译器(g ++clang ++)接受代码作为有效语法,但只有启用情况下才会生成警告 .-pedantic

ISO C++禁止变长数组'vla'[-Wvla]

我的问题是:

  • 为什么编译器接受该声明?
    编译器不能只拒绝一个长度为的数组[is-no-know-at-compile-time]
    是否存在一种兼容性语法规则?

  • 标准说了什么?
    从生成的汇编代码中我看到编译器在循环中写入堆栈,就像普通数组一样,但我找不到任何关于标准行为的信息.

c++ dynamic-arrays

9
推荐指数
2
解决办法
1565
查看次数

GCC无法从模板函数推导出自动返回类型?

我有一个简单的模板函数do_something,它返回一个整数:123.

template<typename T>
auto do_something(T input) {
  std::this_thread::sleep_for(std::chrono::seconds(1));
  return 123;
}

int main(int argc, char *argv[]) {
  std::function<int(void)> function = std::bind(do_something<int>, 12);
  function();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用GCC 6.1.1,我收到此错误:

test.cpp: In function ‘int main(int, char**)’:
test.cpp:16:70: error: no matching function for call to ‘bind(<unresolved overloaded function type>, int)’
   std::function<int(void)> function = std::bind(do_something<int>, 12);
                                                                      ^
In file included from /usr/include/c++/6.1.1/thread:39:0,
                 from test.cpp:4:
/usr/include/c++/6.1.1/functional:1331:5: note: candidate: template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) …
Run Code Online (Sandbox Code Playgroud)

c++ gcc templates type-deduction

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

数组初始化编译时间 - Constexpr序列

我正在读这个问题.

问题本身并不那么有趣,但我想知道它是否存在以及如何实现编译时解决方案.

关于第一个序列:

所有数字除了可以除以3之外的数字.

序列应该是这样的:

[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, ...]
Run Code Online (Sandbox Code Playgroud)

通过归纳,我找到了该序列的数学公式:

 f(0) = 0;
 f(x > 0) = floor[(3x - 1) / 2];
Run Code Online (Sandbox Code Playgroud)

所以我实现了一个C++ constexpr函数,它在序列中生成第i个数字:

#include <type_traits>

template <typename T = std::size_t>
constexpr T generate_ith_number(const std::size_t index) {
  static_assert(std::is_integral<T>::value, "T must to be an integral type");

  if (index == 0) return 0;
  return (3 * index - 1) / 2;
}
Run Code Online (Sandbox Code Playgroud)

现在我想生成一个"编译时数组/序列",它存储序列的前N个数字.

结构应该是这样的:

template <typename …
Run Code Online (Sandbox Code Playgroud)

c++ arrays compile-time constexpr c++11

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

模板专业化与模板参数

我们假设有一个template班级Foo:

template <typename T>
class Foo {
  void foo();
};
Run Code Online (Sandbox Code Playgroud)

我有另一个templateBar(独立于第一个类):

template <int N>
class Bar {};
Run Code Online (Sandbox Code Playgroud)

让我们说,我想专门foo()为任何Bar类的方法.我写错了:

template <>
template <int N>
void Foo<Bar<N> >::foo() { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

编译器指责我,因为类型不完整:

error: invalid use of incomplete type 'class Foo<Bar<N> >'
 void Foo<Bar<N> >::foo() { }
Run Code Online (Sandbox Code Playgroud)

我正在使用C++ 98,但我想知道C++ 11中是否存在不同的解决方案.


注意

我可以解决专门Foo针对泛型的整个类的问题Bar,但是在我必须定义所有方法之后.

示例代码

这不是我想要的,我正在寻找(如果存在)更优雅的解决方案(包括C++ 98和C++ 11),它允许我专门化并实现单个类方法.


编辑:

关于SO的问题没有解释如何专注于模板参数.实际上,我的问题显示了编译器如何抱怨这一点.

c++ templates template-specialization c++11 c++98

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

复制初始化列表中的构造

我在探索丑陋的世界std::intializer_list.

据我所知,从标准:

§11.6.4:

  1. std :: initializer_list类型的对象是从初始化列表构造的,就好像实现生成并实现了(7.4)类型为"const const E"的prvalue,其中N是初始化列表中的元素数.使用初始化列表的相应元素对该数组的每个元素进行复制初始化,并构造std :: initializer_list对象以引用该数组.[注意: 在初始化列表的上下文中,可以访问为副本选择的构造函数或转换函数(第14条). - 尾注] [...]

因此,如果类型E是一个,我希望调用复制构造函数.


以下类不允许复制构造:

struct NonCopyable {
  NonCopyable() = default;   
  NonCopyable(const NonCopyable&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

我将尝试std::initializer_list使用此类实例化一个.

#include <vector>

void foo() {
  std::vector<NonCopyable>{NonCopyable{}, NonCopyable{}};
}
Run Code Online (Sandbox Code Playgroud)

随着g++-8.2 -std=c++14我得到我期望的,编译器错误:

error: use of deleted function 'NonCopyable::NonCopyable(const NonCopyable&)'.

完善!


但是,行为随新标准而变化.

的确,g++-8.2 -std=c++17编译.

编译器资源管理器测试


我认为这是因为copy elision新标准提出的新要求,起初.

但是,更改标准库实现 …

c++ initializer-list copy-elision c++17

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

SFINAE`std :: void_t`类模板专门化

使用SFINAE,我需要检测容器的某些属性。

例如:

#include <type_traits>
#include <vector>

template <typename Container, typename = void>
struct Trait {};

template <typename Container>
struct Trait<
    Container,
    std::enable_if_t<std::is_integral_v<typename Container::value_type>>> {
  static constexpr bool foo = false;
};

template <typename Container>
struct Trait<
     Container, 
     std::enable_if_t<std::is_floating_point_v<typename Container::value_type>>> {
  static constexpr bool foo = true;
};

static_assert(Trait<std::vector<int>>::foo == false);
static_assert(Trait<std::vector<double>>::foo == true);
Run Code Online (Sandbox Code Playgroud)

上面的代码可以按预期进行编译和运行(在clanggcc上)。在这里检查

但是,如果我稍加修改将模板类型包装在里面的代码std::void_t

template <typename Container>
struct Trait<
    Container,
    std::void_t<std::enable_if_t<std::is_integral_v<typename Container::value_type>>>> {
  static constexpr bool foo …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae c++17 void-t

7
推荐指数
0
解决办法
85
查看次数