小编sky*_*ack的帖子

noexcept,继承构造函数和无效使用实际完成的不完整类型

我不确定这是GCC编译器的错误还是预期的行为noexcept.
请考虑以下示例:

struct B {
    B(int) noexcept { }
    virtual void f() = 0;
};

struct D: public B {
    using B::B;
    D() noexcept(noexcept(D{42})): B{42} { }
    void f() override { }
};

int main() {
    B *b = new D{};
}
Run Code Online (Sandbox Code Playgroud)

如果noexcept删除它,它编译.
无论如何,正如在例子中,我从GCC v5.3.1得到了这个错误:

test.cpp:8:31: error: invalid use of incomplete type ‘struct D’
     D() noexcept(noexcept(D{42})): B{42} { }
                               ^
Run Code Online (Sandbox Code Playgroud)

据我所知,struct D不是一个不完整的类型,但继承构造函数涉及到语句,看起来编译器实际上考虑的是基本结构的完整性而B不是D.

这是预期的行为还是合法代码?

为清楚起见:

c++ language-lawyer noexcept c++11 inheriting-constructors

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

折叠表达式和空参数包:预期结果是什么?

请考虑以下最小示例:

#include<cstddef>

template<std::size_t... I>
constexpr auto sum() { return (I + ...); }

template<bool... B>
constexpr auto check() { return (B && ...); }

int main() {
    static_assert(6 == sum<1,2,3>(), "!");
    // static_assert(0 == sum<>(), "!");
    static_assert(check<true, true>(), "!");
    static_assert(check<>(), "!");
}
Run Code Online (Sandbox Code Playgroud)

注释行不编译.
这同样适用于*代替+.
涉及布尔运算的那个相反.

这里(工作草案)我没有找到关于空参数包的提及.
另一方面,这里(isocpp)似乎是上面例子中的默认结果int().

混合折叠表达式和空参数包时,预期的行为是什么?

c++ templates fold-expression c++17

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

如果与通用lambda结合使用,std :: list :: remove_if会变得疯狂

我发现一个问题,我猜是由于GCC中的一个错误.
无论如何,在开启问题之前,我想确定一下.

请考虑以下代码:

#include<algorithm>
#include<list>

template<typename U>
struct S {
    using FT = void(*)(); 
    struct T { FT func; };

    template<typename> 
    static void f() { } 

    std::list<T> l{ { &f<int> }, { &f<char> } };

    void run() {  
        l.remove_if([](const T &t) { return t.func == &f<int>; }); // (1)
        l.remove_if([](const auto &t) { return t.func == &f<int>; }); // (2)
    }
};

int main() {
    S<void> s;
    s.run();
}
Run Code Online (Sandbox Code Playgroud)

clang v3.9 按预期编译(1)(2).
GCC v6.2 编译 …

lambda gcc clang language-lawyer c++14

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

SDL2,gpg :: GameServices和多个窗口

我在基于SDL2构建的本机应用程序中使用C++ SDK for Google Play Game Services.本机部分是在运行时加载的.so文件.

只要我以标准方式使用应用程序,一切正常.另一方面,我遇到了gpg::GameServices使用多窗口时遇到的问题.
当应用程序切换到多窗口模式时,本机部分将离开该main功能并通过设计重新输入.main由于用户正在终止应用程序或者因为切换到多窗口模式,我不知道该函数是否被放弃,因此在函数结束时我gpg::GameServices按照文档中的建议重置指向对象的指针.然后在同一函数的开头重新初始化.

但是,看起来出现了问题,应用程序只是通过以下消息冻结了一段时间:

V/GamesNativeSDK:GameServices清理时间超过15秒或返回错误.在GameServicesImpl可能仍处于活动状态时销毁对象.

20秒后,应用程序按预期再次启动,但这种冻结非常烦人,我无法理解是什么原因.
作为旁注,出于明显的原因打电话FlushFlusBlocking不解决问题(我这样做只是为了检查是否是这种情况).

gpg::GameServices即使应用程序未正确关闭,是否有任何问题终止?我的意思是,当活动被销毁但.so没有被丢弃时,而是创建一个新的活动,并在main之后立即再次调用该函数?

c++ android google-play-services sdl-2

12
推荐指数
0
解决办法
160
查看次数

使用临时存储区复制简单的可复制类型:是否允许?

这个问题是对另一个问题答案的评论的后续跟进.


请考虑以下示例:

#include <cstring>
#include <type_traits>
#include <cassert>

int main() {
    std::aligned_storage_t<sizeof(void*), alignof(void*)> storage, copy;

    int i = 42;
    std::memcpy(&storage, &i, sizeof(int));

    copy = storage;

    int j{};
    std::memcpy(&j, &copy, sizeof(int));

    assert(j == 42);
}
Run Code Online (Sandbox Code Playgroud)

适用于(对某些作品的定义).但是,标准告诉我们这个:

对于任何对象平凡复制的类型的(比基类的其他子对象)T时,对象是否保持类型的有效的值T,构成对象的底层字节可以被复制到的阵列char,unsigned charstd?::?byte.
如果将该数组的内容复制回对象,则该对象应随后保持其原始值.[例如:

#define N sizeof(T)
char buf[N];
T obj;                          // obj initialized to its original value
std::memcpy(buf, &obj, N);      // between these two calls to std?::?memcpy, …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++17

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

变量模板,参数包及其在参数列表中讨论的歧义

在这个问题中,我将参考我之前的问题.

在那个问题中,我发现以下内容无效:

template<typename T, typename... A, typename S>
class C { };
Run Code Online (Sandbox Code Playgroud)

这是因为:

[它不是有效的代码]用于类模板,因为必须始终指定它们的参数,这将始终导致歧义,除非参数包在最后并且填充任何剩余的模板参数.

这是有道理的,当然,我得到了它.

然后,作为替代方法,提出了涉及专业化的以下内容:

template<typename F, typename S>
class C;

template<typename T, typename... A, typename S>
class C<T(A...), S> { };
Run Code Online (Sandbox Code Playgroud)

实际上,它似乎有效,所以感谢提出它的人.

无论如何,我不明白为什么这是有效的代码,而前一个不是.
它是否应该受到先前解决方案的模糊性的影响?在这种情况下,编译器为什么以及如何解决这种模糊性?
根据上一个问题(参见本问题开头的链接),在我看来,仍然可变参数部分应该将任何参数填充到最后,因此该代码也不应该是有效的.
当然,我错了,但在我的推理中究竟出了什么问题?

c++ templates variadic-templates c++11

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

当我只想禁用它时,自定义赋值运算符=()的签名是否重要?

我需要禁用复制赋值运算符.这将有效:

A& operator=(const A&);
Run Code Online (Sandbox Code Playgroud)

如果我没有指定确切的参数,它会工作operator=吗?
我的意思是这样的:

void operator=(void);
Run Code Online (Sandbox Code Playgroud)

返回值是正确的,我可以写任何我想要的,但参数类型怎么样?
这会覆盖operator=类的默认值吗?

c++ operator-overloading assignment-operator

11
推荐指数
3
解决办法
1443
查看次数

decltype(void())和decltype(void {})之间的差异

这是问题的一个后续:什么是void()decltype(void())意味着什么?.


decltype(void())编译好,void()在这种情况下的手段在上述问题中解释(实际上在答案中).
另一方面,我注意到decltype(void{})没有编译.

它们之间有什么区别(decltype至少在上下文中)?
为什么第二个表达式不能编译?


为了完整起见,它遵循一个最小的(不是)工作示例:

int main() {
    // this doesn't compile
    //decltype(void{}) *ptr = nullptr;
    // this compiles fine
    decltype(void()) *ptr = nullptr;
    (void)ptr;
}
Run Code Online (Sandbox Code Playgroud)

c++ void decltype language-lawyer c++11

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

关于涉及唯一指针的安全操作

请考虑以下代码:

#include <memory>

struct Foo { std::unique_ptr<Foo> next; };
void f(Foo &foo) { foo = std::move(*foo.next); }

int main() {
    Foo foo{};
    foo.next = std::make_unique<Foo>();
    foo.next->next = std::make_unique<Foo>();
    f(foo);
}
Run Code Online (Sandbox Code Playgroud)

通过这样做foo = std::move(*foo.next);,foo.next.next被移动到foo.next.
如果foo.next作为第一步失效,则可以立即删除它指向的对象.这将导致删除foo.next.next,这是我试图移动的对象foo.next.
我很确定我在推理中遗漏了一些东西,但我无法弄清楚出了什么问题.
这是安全的操作吗?标准在哪里让我放心?

c++ unique-ptr c++14

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

扣除指南,模板和子对象:哪个编译器是对的?

请考虑以下代码段:

struct S {
    S() {}

    template<typename B>
    struct T {
        T(B &&) {}
    };

    template<typename B>
    T(B &&) -> T<B>;
};

int main() {
    S::T t{0};
}
Run Code Online (Sandbox Code Playgroud)

Clang 接受它,而GCC 拒绝代码时出现以下错误:

prog.cc:10:5:错误:演绎指南'S :: T(B &&) - > S :: T'必须在命名空间范围内声明

这是有效的代码吗?哪个编译器是对的,GCC还是Clang?

c++ templates language-lawyer template-argument-deduction c++17

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