标签: c++17

为什么S :: x没有使用?

cppreference考虑这个例子:

struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x
Run Code Online (Sandbox Code Playgroud)

我同意这&S::x是一个废弃值表达式,因为标准说(9.2,第1段[stmt.expr]来自n4700)

表达式语句具有表单

expression-statement:
    expression_opt ;
Run Code Online (Sandbox Code Playgroud)

表达式是一个废弃值表达式(第8条)......

但是,这是否足够S::x不被使用?6.2,第3段[basic.def.odr]指出

一种可变x为潜在评估表达式出现的名字exODR使用的ex除非

  • ...
  • if x是一个对象,ex是表达式的潜在结果集的一个元素e,其中任何一个
    • 左值到左值的转换(7.1)适用于e
    • e是丢弃值表达式(第8条).

问题是丢弃值表达式&S::x没有潜在的结果(这意味着它S::x不是潜在的结果&S::x),如6.2,第2段[basic.def.odr]所示:

...表达式的潜在结果集e定义如下:

  • 如果e是id-expression(8.1.4),则该集仅包含e. …

c++ language-lawyer c++17

51
推荐指数
1
解决办法
1681
查看次数

静态constexpr和C++ 17中的静态内联变量有什么区别?

使用C++ 17,我们得到内联变量.

其中一个用途是在类中定义常量字段.

那么这两个常量定义之间的区别是什么:

class MyClass {
    static constexpr int myFirstVar = 10;
    static const inline int mySecondVar = 100;
};
Run Code Online (Sandbox Code Playgroud)

当然constexprmyFirstVar隐式内联.

什么是更好的选择,使用constexprinline

注意:当你不需要constness时,那就inline更容易了.随着constexpr你没有这样的选择.

c++ c++17

50
推荐指数
1
解决办法
8320
查看次数

在现代C++中是否可以将字符串文字作为参数传递给C++模板?

是否可以在"现代C++"(C++ 17或更高版本)中将字符串文字作为参数传递给C++模板?

我意识到你可以用构造函数参数做到这一点; 我只是认为将它作为模板参数更方便,而不是深埋在cpp文件中.如果这可能是现代C++的一个新功能,我很好奇.请参阅下面的伪代码我正在尝试做的事情:

伪代码示例:

// Header File /////////////////////////
template<constexpr string Name>
class ModuleBase {
public:
    ModuleBase();
    string name;
};

class xyz : ModuleBase<"xyz"> {
public:
    xyz();
};

// Cpp File //////////////////////////
template<string_literal Name>
ModuleBase<Name>::ModuleBase() {
    name = Name;
}

xyz::xyz() : ModuleBase() {

}
Run Code Online (Sandbox Code Playgroud)

c++ c++17 c++20

50
推荐指数
1
解决办法
3468
查看次数

为什么这段代码在 C++17 中编译没有错误?

我已经删除了所有的构造函数,即使下面的代码运行良好。如何以及为什么?

class Ax
{    
    public:
    
    Ax() = delete;
    Ax(Ax const&)=delete;
    Ax(Ax&&)=delete;
    void operator=(Ax const&)=delete;
    void operator=(Ax&&)=delete;

    void print()
    {
        cout << "Hello \n";
    }
};

int main(int argc, char** argv) 
{           
    Ax{}.print();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ c++17

49
推荐指数
2
解决办法
3938
查看次数

三元运算符隐式转换为基类

考虑一下这段代码:

struct Base
{
    int x;
};

struct Bar : Base
{
    int y;
};

struct Foo : Base
{
    int z;
};

Bar* bar = new Bar;
Foo* foo = new Foo;

Base* returnBase()
{
    Base* obj = !bar ? foo : bar;
    return obj;
}

int main() {
    returnBase();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这在Clang或GCC下不起作用,给我:

错误:不同指针类型'Foo*'和'Bar*'之间的条件表达式缺少一个强制转换Base*obj =!bar?foo:bar;

这意味着要编译我必须将代码更改为:

Base* obj = !bar ? static_cast<Base*>(foo) : bar;
Run Code Online (Sandbox Code Playgroud)

由于隐式转换为Base*存在,是什么阻止编译器这样做?

换句话说,为什么没有Base* obj = foo;演员而是使用?:操作员的工作呢?是因为我不清楚我想使用这Base部分吗?

c++ ternary-operator language-lawyer implicit-conversion c++17

48
推荐指数
3
解决办法
2530
查看次数

集成初始化的C++ 17扩展是否使得大括号初始化变得危险?

似乎普遍认为,大括号初始化应优先于其他形式的初始化,但是由于将C++ 17 扩展引入聚合初始化,似乎存在意外转换的风险.请考虑以下代码:

struct B { int i; };
struct D : B { char j; };
struct E : B { float k; };

void f( const D& d )
{
  E e1 = d;   // error C2440: 'initializing': cannot convert from 'D' to 'E'
  E e2( d );  // error C2440: 'initializing': cannot convert from 'D' to 'E'
  E e3{ d };  // OK in C++17 ???
}

struct F
{
  F( D d ) …
Run Code Online (Sandbox Code Playgroud)

c++ initialization list-initialization c++17

48
推荐指数
2
解决办法
3893
查看次数

为什么`std :: stringstream :: stringstream(std :: string &&)`不存在?

我希望stringstream有一个构造函数窃取其初始内容string&&.STL中通常不存在这样的种间"移动构造函数"吗?如果没有,为什么不呢?

c++ stringstream rvalue-reference move-semantics c++17

48
推荐指数
2
解决办法
2145
查看次数

确定函数返回类型的最简单方法

给出一个非常简单但冗长的功能,例如:

int foo(int a, int b, int c, int d) {
    return 1;
}

// using ReturnTypeOfFoo = ???
Run Code Online (Sandbox Code Playgroud)

在编译时确定函数返回类型(ReturnTypeOfFoo在本例中int为:) 的最简单,最简洁的方法是什么,而不重复函数的参数类型(仅限名称,因为已知该函数没有任何额外的重载)?

c++ function return-type compile-time c++17

48
推荐指数
3
解决办法
2617
查看次数

C++标准是否保证统一初始化是异常安全的?

#include <iostream>

using namespace std;

struct A
{
    A() { cout << "A" << endl; }
    ~A() { cout << "~A" << endl; }
};

A Ok() { return {}; }
A NotOk() { throw "NotOk"; }

struct B
{
    A a1;
    A a2;
};

void f(B) {}

int main()
{
    try
    {
        f({ Ok(), NotOk() });
    }
    catch (...)
    {}
}
Run Code Online (Sandbox Code Playgroud)

vc++clang输出:

A
~A
Run Code Online (Sandbox Code Playgroud)

虽然gcc产出:

A
Run Code Online (Sandbox Code Playgroud)

这似乎是GCC的一个严重错误.

供参考,参见GCC bug 66139AndrzejKrzemieński撰写的"GCC中的一个严重错误" …

c++ gcc exception uniform-initialization c++17

47
推荐指数
1
解决办法
1754
查看次数

使一个函数接受一个可选的接受非可选的?

我正在尝试以monad风格编写语法糖std::optional.请考虑:

template<class T>
void f(std::optional<T>)
{}
Run Code Online (Sandbox Code Playgroud)

即使存在从22的转换,也不能使用非可选T1(例如an int)调用此函数.Tstd::optional<T>

有没有办法f接受a std::optional<T>或a T(在调用者站点转换为可选),而没有定义过载3


1) f(0):error: no matching function for call to 'f(int)'note: template argument deduction/substitution failed,(演示).
2)因为模板参数推导不考虑转换.
3)超载是用于一个一元函数的可接受的解决方案,但开始是当你有像二进制功能的烦恼operator+(optional, optional),并且是用于三元疼痛,4元,等等功能.

c++ templates optional template-argument-deduction c++17

47
推荐指数
4
解决办法
2765
查看次数