小编son*_*yao的帖子

在C++ 17中更改了受保护构造函数的规则?

我有这个测试用例:

struct A{ protected: A(){} };
struct B: A{};
struct C: A{ C(){} };
struct D: A{ D() = default; };

int main(){
    (void)B{};
    (void)C{};
    (void)D{};
}
Run Code Online (Sandbox Code Playgroud)

gcc和clang都用C++ 11和C++ 14模式编译它.两者都在C++ 17模式下失败:

$ clang++ -std=c++17 main.cpp 
main.cpp:7:10: error: base class 'A' has protected default constructor
        (void)B{};
                ^
main.cpp:1:22: note: declared protected here
struct A{ protected: A(){} };
                     ^
main.cpp:9:10: error: base class 'A' has protected default constructor
        (void)D{};
                ^
main.cpp:1:22: note: declared protected here
struct A{ protected: A(){} };
                     ^
2 …
Run Code Online (Sandbox Code Playgroud)

c++ constructor protected language-lawyer c++17

60
推荐指数
2
解决办法
3501
查看次数

为什么派生类在基类不可移动时可以构造?

请考虑以下示例:

#include <iostream>
#include <string>
#include <utility>

template <typename Base> struct Foo : public Base {
    using Base::Base;
};

struct Bar {
    Bar(const Bar&) { }
    Bar(Bar&&) = delete;
};

int main() {
    std::cout << std::is_move_constructible<Bar>::value << std::endl; // NO
    std::cout << std::is_move_constructible<Foo<Bar>>::value << std::endl; // YES. Why?!
}
Run Code Online (Sandbox Code Playgroud)

尽管基类是不可移动构造的,为什么编译器会生成移动构造函数?

这是标准还是编译器错误?是否有可能"完美地传播"将构造从基础移动到派生类?

c++ language-lawyer move-constructor move-semantics c++11

57
推荐指数
2
解决办法
2049
查看次数

初始化零数组

众所周知,标量数组的缺少初始值设定值默认为零.

int A[5]; // Entries remain uninitialized
int B[5]= { 0 }; // All entries set to zero
Run Code Online (Sandbox Code Playgroud)

但是这(下面)保证了吗?

int C[5]= { }; // All entries set to zero
Run Code Online (Sandbox Code Playgroud)

c++ arrays initialization language-lawyer

53
推荐指数
3
解决办法
3万
查看次数

模板默认参数丢失其引用类型

考虑

#include <iostream>
#include <type_traits>

template <class T, class ARG_T = T&>
T foo(ARG_T v){
    return std::is_reference<decltype(v)>::value;
}

int main() {
    int a = 1;
    std::cout << foo<int>(a) << '\n';
    std::cout << foo<int, int&>(a) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

我希望两种情况下的输出均为1。但在第一种情况下为0:与默认值class ARG_T = T而不是一致class ARG_T = T&

我想念什么?

c++ templates function-templates template-argument-deduction argument-deduction

43
推荐指数
2
解决办法
966
查看次数

为什么const成员可以初始化两次?

下面是一个代码片段,可以在vs2015中编译和运行而不会出错

#include<iostream>
using namespace std;

class A {
    public:
        A(int b) :k(b) {}//second time
    const int k = 666;//first time
};

int main() {
    A a(555);
    cout << a.k << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是555.但据我所知,const对象应该只初始化一次,之后值不可修改.

c++ initialization const initializer-list c++11

39
推荐指数
2
解决办法
2877
查看次数

为什么"自动ch = unsigned char {'p'}"在C++ 17下编译?

我很困惑.不是const auto ch = unsigned char{'p'};一个完全有效的初始化表达式?所有三个主要编译器都无法使用几乎相同的错误消息进行编译:

错误:预期'('用于函数式转换或类型构造

交换花括号('p')没有任何变化.但是,它确实在没有signedor unsigned关键字的情况下编译.

在线演示.

c++ language-lawyer c++14 c++17

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

大括号的类型如何影响 C++ 中的对象生命周期?

我的一个朋友给我看了一个 C++20 程序:

#include <iostream>

struct A
{
    A() {std::cout << "A()\n";}
    ~A() {std::cout << "~A()\n";}
};

struct B
{
    const A &a;
};

int main()
{
    B x({});
    std::cout << "---\n";
    B y{{}};
    std::cout << "---\n";
    B z{A{}};
    std::cout << "---\n";
}
Run Code Online (Sandbox Code Playgroud)

在 GCC 中,它打印:

A()
~A()
---
A()
---
A()
---
~A()
~A()
Run Code Online (Sandbox Code Playgroud)

https://gcc.godbolt.org/z/ce3M3dPeo

因此,A在 y 和 z 情况下,的寿命会延长。

在 Visual Studio 中,结果是不同的:

A()
~A()
---
A()
---
A()
~A()
---
~A()
Run Code Online (Sandbox Code Playgroud)

所以A只有在 y …

c++ initialization object-lifetime temporary-objects c++20

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

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

执行std :: forward

我正在阅读新C++概述(C++ 11/14)(仅限PDF),在幻灯片288中它给出了一个实现std::forward:

template<typename T>                // For lvalues (T is T&),
T&& std::forward(T&& param)         // take/return lvalue refs.
{                                   // For rvalues (T is T),
    return static_cast<T&&>(param); // take/return rvalue refs.
}
Run Code Online (Sandbox Code Playgroud)

然后在文本中给出另一个实现:

通常的std :: forward实现是:

template<typename T>
struct identity {
    typedef T type;
};
template<typename T>
T&& forward(typename identity<T>::type&& param)
{ return static_cast<identity<T>::type&&>(param); }
Run Code Online (Sandbox Code Playgroud)

有什么不同?为什么后者通常是实施?

c++ c++11

30
推荐指数
3
解决办法
7457
查看次数

C++ 可以从默认值推导出参数类型吗?

我尝试使用默认模板参数编写此函数:

template<typename A, typename B>
void func(int i1, int i2, A a, B b = 123){
    ...
}
Run Code Online (Sandbox Code Playgroud)

在我看来,我可以这样称呼它:func(1, 2, 3)编译器应该从默认值推断出类型Bint但我得到了no instance of overloaded function
在这种情况下,C++ 构造是否不正确并且编译器无法推断出类型?

c++ templates default default-arguments template-argument-deduction

30
推荐指数
2
解决办法
2643
查看次数