小编Ami*_*rsh的帖子

访问友元类私有成员的友元函数

跟随2019 年特拉维夫欧洲电视网的捷克歌曲

众所周知,在 C++ 中,朋友的朋友不是(自动地)朋友。

然而,Clang 在 GCC 和 MSVC 的以下代码上有所不同:

class A {
public:    
    // forward declaration
    class Inner2;

private:
    class Inner1 {
        char foo;
        friend class Inner2;
    };
public:
    class Inner2 {
        Inner1 i;
    public:
        bool operator==(Inner2 other) {
            return i.foo == other.i.foo; // OK by GCC, Clang and MSVC++
        }
        friend bool operator!=(Inner2 a, Inner2 b) {
            return a.i.foo != b.i.foo; // Clang accepts, GCC and MSVC++ reject
        }
    };
};
Run Code Online (Sandbox Code Playgroud)

代码:https …

c++ friend friend-function friend-class

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

未知类型的模板模板参数

尝试在以下代码中提取模板参数值:

template<std::size_t SIZE>
class Foo {};

template <template<std::size_t> class T, std::size_t K>
auto extractSize(const T<K>&) {
    return K;
}

int main() {
    Foo<6> f1;
    Foo<13> f2;
    std::cout << extractSize(f1) << std::endl;
    std::cout << extractSize(f2) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

(作为问题的答案: 提取C++模板参数).

但是,有没有办法在不知道模板参数类型的情况下执行此操作.类似的东西(下面的代码不能编译......):

template <template<class SIZE_TYPE> class T, SIZE_TYPE K>
auto extractSize(const T<K>&) {
    return K;
}
Run Code Online (Sandbox Code Playgroud)

编译错误:

error: unknown type name 'SIZE_TYPE'
template <template<class SIZE_TYPE> class T, SIZE_TYPE K>
                                             ^
Run Code Online (Sandbox Code Playgroud)

c++ templates c++11 c++14

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

为什么unique_ptr::release 没有用[[nodiscard]] 定义?

C++17添加了[[nodiscard]].

C++20添加了[[nodiscard]]onempty方法的使用,例如——也许是为了避免用户与方法 clear 混淆(即意外调用empty()清除向量)。vector::empty()

为什么 C++20 没有利用这个机会添加[[nodiscard]]unique_ptr::release?


是否存在一种有效的合理场景,即在unique_ptr::release不获取返回值的情况下进行调用?


以同样的方式避免用户混淆(如果这是添加[[nodiscard]]empty方法的原因) - 名称release总是非常混乱,听起来像,嗯......这里将发布一些东西。

添加[[nodiscard]]可以在某种程度上解决这个名称问题。

c++ unique-ptr

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

`constexpr` 函数的 `noexcept` 行为

[expr.unary.noexcept]的措辞在C++17 中发生了变化。


以前(n4140, 5.3.7 noexcept operator [expr.unary.noexcept]),我的重点是

  1. 如果在潜在求值的上下文中表达式将包含,则 noexcept 运算符的结果为 false

    (3.1) 对不具有非抛出异常规范 ([except.spec]) 的函数、成员函数、函数指针或成员函数指针的潜在求值调用,除非调用是常量表达式 ([ expr.const]) ...


现在17.6.2.6 noexcept 运算符 [expr.unary.noexcept]):

  1. 除非表达式可能抛出异常 ([except.spec]),否则noexcept 运算符的结果为

然后在14.5 异常规范 [except.spec] 中

  1. 如果函数声明没有 noexcept 说明符,则该声明具有潜在的抛出异常说明,除非...

但是14.5(3)的除非列表未列出constexpr,因此可能会抛出...

1 LF 在评论中添加的指向 C++17 n4659的链接。


测试代码

constexpr int f(int i) { return i; }

std::cout << boolalpha << noexcept(f(7)) << std::endl;
int a = 7;
std::cout …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer noexcept constexpr c++17

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

基于数组大小有效性的专业化

尝试根据数组大小的有效性进行专业化:

// base template
template<int p, typename T = void>
struct absolute {
    operator int () const { return 0; }
};

// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
    operator int () const { return p; }
};

// negative case template
template<int p>
struct absolute<p, typename std::void_t<int[-p]>> {
    operator int () const { return -p; }
};


int main() {
    std::cout << absolute<5>() << std::endl;
    std::cout << absolute<-5>() << std::endl;
    std::cout << absolute<0>() << std::endl; …
Run Code Online (Sandbox Code Playgroud)

c++ template-specialization

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

为什么C++禁止最终类的私有继承?

C++ 11将final关键字引入了C++.

它可以在虚拟方法类上使用.

声明一个类最终禁止任何类型的继承:public,protected和private.

struct A final {
};

class B: private A {
};

 error: base 'A' ^ is marked 'final'
Run Code Online (Sandbox Code Playgroud)

虽然禁止公共继承是合理的(例如,如果我的类没有虚拟析构函数,或者出于其他原因),为什么我应该禁止私有继承?

可能是因为如果final禁止公共继承,那它std::string和std中的其他朋友会final- 因为他们应该 - 因为没有虚拟的析构函数?

编辑:

Howard Hinnant已经回答了为什么标准集装箱不是最终的,但仍然有理由宣布一个班级决赛,但允许私人继承.

c++ final

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

C++20 中的 std::launder 用例

[1]

\n\n

是否有任何情况不需要将p0593r6添加到 C++20 ( \xc2\xa7 6.7.2.11对象模型[intro.object] ) std::launder,而需要 C++17 中的相同用例std::launder,或者它们是完全正交?

\n\n
\n\n

[2]

\n\n

[ptr::launder]规范中的示例是:

\n\n
struct X { int n; };\nconst X *p = new const X{3};\nconst int a = p->n;\nnew (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const\nconst int b = p->n;                 // undefined behavior\nconst int c = std::launder(p)->n;   // OK\n
Run Code Online (Sandbox Code Playgroud)\n\n

@Nicol Bolas在这个 SO 答案中给出了另一个例子,使用指向有效存储但类型不同的指针:

\n\n …

c++ language-lawyer c++20 stdlaunder

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

在 C++20 之前,使用常量或引用字段在 `A` 上调用 `std::vector&lt;A&gt;::data()`

这是在具有参考字段的类上放置 new的答案的后续。

调用std::vector<A>::data()上型A具有参考常量字段,将指针返回到对象可通过原始向量通过放置新的,这将导致一个的const或参考场来改变原始对象将被替换,而仍然被另一指针管理,通过调用返回data()

例如:

struct A {
    const int i = 0;
};

int main() {
    std::vector<A> vec = {{1}, {2}};
    auto ptr = vec.data();
    std::cout << ptr[1].i << std::endl; // 2
    vec.pop_back();
    vec.push_back({3}); // placement new, inside
    std::cout << ptr[1].i << std::endl; // 3
}
Run Code Online (Sandbox Code Playgroud)

C++17 试图通过引入来解决这些问题,std::launder但后来同意虽然std::launder可以解决其他问题,但它并没有真正解决上述用例的问题,如NB US042 中所述

一些问题 - 对于C++20 之前的C++ 版本:

  • 由于NB US042 …

c++ placement-new language-lawyer c++20

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

从一系列字符构建 string_view

虽然 aspan可以从范围构造,string_view但不能从字符范围构造。

因此,例如,需要以下代码:

// assume chars_span is a span of chars
std::cout << std::string_view(chars_span.data(), chars_span.size());
// or:
std::cout << std::string_view(chars_span.begin(), chars_span.end());
Run Code Online (Sandbox Code Playgroud)

而不是不支持的更简单的范围语法

std::cout << std::string_view(chars_span);
Run Code Online (Sandbox Code Playgroud)

是否有理由没有string_view接受一系列字符的构造函数,或者它只是被忽视或被认为不够重要?

c++ string-view c++20

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

具有不同参数类型的受约束函数模板与无约束函数模板

在下面的两个模板函数中,我们尝试了更多的约束:

template<typename T>
concept SmallVar = (sizeof(T) <= sizeof(int));

void print(SmallVar auto t) { // 1
    std::cout << t << std::endl;
}

void print(const auto& t) {   // 2 
    std::cout << t << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

当使用 int 调用时,Clang 和 GCC 有所不同:

int main() {
    print(6);  // clang accepts and prefers 1, gcc sees here ambiguity
}
Run Code Online (Sandbox Code Playgroud)

哪一个是正确的?

代码: https: //godbolt.org/z/x71zjzoTa

c++ templates c++20 function-templates-overloading

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