小编dfr*_*fri的帖子

在内联函数的定义中使用 constexpr 变量时可能发生 ODR 违规(在 C++14 中)

(注意!这个问题特别涵盖了 C++17 中引入内联变量之前 C++14 的状态)

太长了;问题

  • 什么构成了在内联函数定义中使用 constexpr 变量的 odr 使用,使得该函数的多个定义违反了 [basic.def.odr]/6?

(...可能是 [basic.def.odr]/3;但是一旦在内联函数定义的上下文中获取这样一个 constexpr 变量的地址,这是否可以在程序中默默地引入 UB?)

TLDR 示例:执行一个程序,其doMath()定义如下:

// some_math.h
#pragma once

// Forced by some guideline abhorring literals.
constexpr int kTwo{2};
inline int doMath(int arg) { return std::max(arg, kTwo); }
                                 // std::max(const int&, const int&)
Run Code Online (Sandbox Code Playgroud)

一旦doMath()在两个不同的翻译单元中定义(例如通过包含some_math.h并随后使用doMath()),就会有未定义的行为吗?

背景

考虑以下示例:

// constants.h
#pragma once
constexpr int kFoo{42};

// foo.h
#pragma once
#include "constants.h"
inline int foo(int arg) { return arg * kFoo; …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++14

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

如何改进此算法以防止TLE是SPOJ提交?

我试图解决以下问题:http: //www.spoj.pl/problems/TRIP/

我在C++中使用DP(动态编程)编写了一个解决方案(下面发布的代码).但我得到了TLE(时间限制超过).如何优化我的代码?

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>

using namespace std;
string a,b;
vector<string> v;
int dp[85][85];

void filldp()
{
    for(int i = 0; i <= a.length(); i++)
        dp[i][0] = 0;
    for(int i = 0; i <= b.length(); i++)
        dp[0][i] = 0;   

    for(int i = 1; i <= a.length(); i++)
        for(int j = 1; j<= b.length(); j++)
        if(a[i-1] == b[j-1])
            dp[i][j] = dp[i-1][j-1] + 1;
        else
            dp[i][j] = max(dp[i-1][j], dp[i][j-1]); 
}

vector<string> fillv(int i, int j) …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm dynamic-programming data-structures

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

对于(U)Int8/16/32/64类型,是否可以将Swifts自动数值桥接复制到Foundation(NSNumber)?

  • 是否有可能复制雨燕数值桥接基金会:■ NSNumber引用类型,例如Int32,UInt32,Int64UInt64类型?具体来说,复制下面介绍的自动按配置桥接.

此类解决方案的示例用法:

let foo : Int64 = 42
let bar : NSNumber = foo
    /* Currently, as expected, error:
       cannot convert value of type 'Int64' to specified type 'NSNumber */
Run Code Online (Sandbox Code Playgroud)

背景

一些原生的Swift数(值)类型可以自动桥接到NSNumber(引用)类型:

迅数字结构类型的实例,例如Int,UInt, Float,Double,和Bool,不能由来表示 AnyObject类型,因为AnyObject仅代表一个类类型的实例.但是,Foundation启用桥接时,可以将Swift数值分配给常量和AnyObject类型的变量 作为类的桥接实例NSNumber.

...

雨燕自动填补某些本地号码类型,如IntFloat,对NSNumber.此桥接允许您NSNumber从以下类型之一创建 : …

nsnumber swift swift2

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

提供给 std::unique_ptr 的简单自定义删除器 lambda:为什么使用按引用捕获默认值 ([&amp;]) 而不是非捕获 ([])?

背景

Cppreference:s部分std::unique_ptr显示了以下演示,用于为unique_ptr实例提供自定义删除器:

std::unique_ptr<D, std::function<void(D*)>> p(new D, [&](D* ptr)
{
    std::cout << "destroying from a custom deleter...\n";
    delete ptr;
});
Run Code Online (Sandbox Code Playgroud)

D就这个问题而言,where就是简单的自定义类型,比如说

struct D
{
    D() { std::cout << "D CTOR\n"; }
    ~D() { std::cout << "D DTOR\n"; }
};
Run Code Online (Sandbox Code Playgroud)

此外,上面的参考资料说明了对删除器的以下类型要求:

类型要求

Deletermust be FunctionObjector lvalue reference to a FunctionObjector lvalue reference to function, callable with an argument of typeunique_ptr<T, Deleter>::pointer

...

会员类型

pointer:std::remove_reference<Deleter>::type::pointer如果该类型存在,否则T*. 必须满足NullablePointer。 …

c++ lambda

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

std::optional:不参与重载决议与被定义为已删除

我试图了解类型特征传播背后的机制,如http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0602r4.html 中std::optional 所述。复制操作的处理有细微的差别,复制操作应有条件地定义为删除,而移动操作则不应参与重载决议。

这种差异的原因是什么,我将如何测试后者?例子:

#include <type_traits>
#include <optional>

struct NonMoveable {
  NonMoveable() = default;
  NonMoveable(NonMoveable const&) = default;
  NonMoveable(NonMoveable&&) = delete;
  NonMoveable& operator=(NonMoveable const&) = default;
  NonMoveable& operator=(NonMoveable&&) = delete;
};

// Inner traits as expected
static_assert(!std::is_move_constructible<NonMoveable>::value);
static_assert(!std::is_move_assignable<NonMoveable>::value);

// The wrapper is moveable, via copy operations participating in
// overload resolution. How to verify that the move operations don't?
static_assert(std::is_move_constructible<std::optional<NonMoveable>>::value);
static_assert(std::is_move_assignable<std::optional<NonMoveable>>::value);

int main(int argc, char* argv[])
{
  NonMoveable a1;
  NonMoveable a2{std::move(a1)}; // Bad, as expected
  std::optional<NonMoveable> b1;
  std::optional<NonMoveable> …
Run Code Online (Sandbox Code Playgroud)

c++ optional overload-resolution

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

(特别是显式)专业化中模板参数列表的访问检查规则

以下所有标准参考均指N4659:2017 年 3 月后 Kona 工作草案/C++17 DIS


考虑以下类模板A和类B,其私有定义了嵌套类C和枚举类E

template<typename T, typename U>
class A {};

class B { 
    class C {};
    enum class E {};
};
Run Code Online (Sandbox Code Playgroud)

根据[temp.explicit]/12

通常的访问检查规则不适用于用于指定显式实例化的名称。[...]

在指定显式实例化时,我们可以参考例如模板参数列表中的B::C和等私有类型B::E

// OK: explicit instantiation definition.
template class A<B::C, B::E>;
Run Code Online (Sandbox Code Playgroud)

我试图在标准中找到类似的部分,该部分指定在为(部分和特别显式/完全)专业化指定模板参数列表时是否同样放弃访问权限限制。

// Partial specialization.
template<typename U>
class A<B::C, U> {};

// Explicit(/full) specialization.
template<>
class A<B::C, B::E> {};
Run Code Online (Sandbox Code Playgroud)

部分专业化无法在 Clang 中编译

error: 'C' is a private …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization language-lawyer

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

使用已删除或非用户提供的私有析构函数构造(但不破坏)类的对象

以下代码片段格式正确吗?

struct A { ~A() = delete; };
A *pa{new A{}};

class B { ~B() = default; };
B *pb{new B{}};
Run Code Online (Sandbox Code Playgroud)

A乍一看,B似乎从未使用过的已删除 dtor和私有显式默认 dtor从未使用过(有意的内存泄漏,如果您愿意的话),这可以说是格式良好的。

Clang 接受各种编译器和 C++ 版本(C++11 到 C++2a)的程序。

另一方面,GCC 拒绝针对各种编译器和 C++ 版本的程序。

struct A { ~A() = delete; };
A *pa{new A{}};  // GCC error: use of deleted function 'A::~A()'

class B { ~B() = default; };
B *pb{new B{}};  // GCC error: 'B::~B()' is private within this context
Run Code Online (Sandbox Code Playgroud)

(如果格式正确;在我提交错误报告之前:是否有针对此极端情况的任何开放的 GCC 错误报告?我自己搜索了 GCC:s bugzilla 无济于事。) …

c++ gcc language-lawyer compiler-bug

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

派生类友元成员访问规则,其中命名类为基类

除非另有说明,否则以下所有标准参考均指N4861(2020 年 3 月布拉格后工作草案/C++20 DIS)


背景

根据[class.access.base]/5

如果基类是可访问的,则可以将指向派生类的指针隐式转换为指向该基类的指针 [...]。

这意味着以下示例是格式良好的:

class N {};

class P : private N {
    friend void f();
};

void f()  { 
    P p{};
    N* n = &p; // R: OK as per [class.access.base]/5
}
Run Code Online (Sandbox Code Playgroud)

asNR上面(+)处的可访问基类。

[class.access.base]/5 还提到[强调我的]:

对成员的访问受命名该成员的类的影响。此命名类是在其中查找并找到成员名称的类。[注: [...]如果两个类成员访问运算符和一个合格-ID被用于命名构件(如在 p->T?::?m),类命名构件是由合格的嵌套名称说明符所表示的类-id(即,T)。—尾注 ]

和[强调我的]:

一个成员在类中命名时m可以访问,如果R N

  • [...]
  • /5.3m作为的成员 N …

c++ language-lawyer

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

来自空大括号的模糊复制赋值的编译器差异

我一直在试图理解std::nullopt_t不允许DefaultConstructible在 C++17(引入它的地方)及更高版本中的基本原理,并在此过程中解决了一些编译器差异混淆。

考虑以下违反规范的(它是DefaultConstructible)实现nullopt_t

struct nullopt_t {
    explicit constexpr nullopt_t() = default;
};
Run Code Online (Sandbox Code Playgroud)

它是 C++11 和 C++14(无用户提供的构造函数)中的聚合,但不是 C++17(构造函数explicit)和 C++20(用户声明的构造函数)中的聚合。

现在考虑以下示例:

struct S {
    constexpr S() {}
    S(S const&) {}
    S& operator=(S const&) { return *this; }   // #1
    S& operator=(nullopt_t) { return *this; }  // #2
};

int main() {
    S s{};
    s = {};  // GCC error: ambiguous overload for 'operator=' (#1 and #2)
}
Run Code Online (Sandbox Code Playgroud)

这在 …

c++ gcc clang language-lawyer compiler-bug

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

是 enum E { a } e = E(2); 有效的?

最近提出一个有趣的 C 语言律师问题:

此问答针对 C++ (*)的类似情况提出了相同的问题:这些是否有效?

enum EA { a } ea = EA(2);               // #1
enum EB { b } eb = static_cast<EB>(2);  // #2
Run Code Online (Sandbox Code Playgroud)

我已经注意到,该变体在编译时被拒绝(“无法用‘ ’类型的右值初始化‘ ’类型的enum EC { c } ec = EC{2};值),而和被接受,排除格式错误但不排除格式错误的 NDR 和 UB对于和。Eint#1#2#1#2


(*) 在被提示对最初的 C 语言律师问题给出过于热切和错误的以 C++ 为中心的答案后,在此发布为自我回答的问答。

c++ enums language-lawyer

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