从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)
表达式语句具有表单
Run Code Online (Sandbox Code Playgroud)expression-statement: expression_opt ;表达式是一个废弃值表达式(第8条)......
但是,这是否足够S::x不被使用?6.2,第3段[basic.def.odr]指出
一种可变
x为潜在评估表达式出现的名字ex被ODR使用的由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++ 17,我们得到内联变量.
其中一个用途是在类中定义常量字段.
那么这两个常量定义之间的区别是什么:
class MyClass {
static constexpr int myFirstVar = 10;
static const inline int mySecondVar = 100;
};
Run Code Online (Sandbox Code Playgroud)
当然constexpr是myFirstVar隐式内联.
什么是更好的选择,使用constexpr或inline?
注意:当你不需要constness时,那就inline更容易了.随着constexpr你没有这样的选择.
是否可以在"现代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) 我已经删除了所有的构造函数,即使下面的代码运行良好。如何以及为什么?
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) 考虑一下这段代码:
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
似乎普遍认为,大括号初始化应优先于其他形式的初始化,但是由于将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) 我希望stringstream有一个构造函数窃取其初始内容string&&.STL中通常不存在这样的种间"移动构造函数"吗?如果没有,为什么不呢?
给出一个非常简单但冗长的功能,例如:
int foo(int a, int b, int c, int d) {
return 1;
}
// using ReturnTypeOfFoo = ???
Run Code Online (Sandbox Code Playgroud)
在编译时确定函数返回类型(ReturnTypeOfFoo在本例中int为:) 的最简单,最简洁的方法是什么,而不重复函数的参数类型(仅限名称,因为已知该函数没有任何额外的重载)?
#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的一个严重错误.
我正在尝试以monad风格编写语法糖std::optional.请考虑:
template<class T>
void f(std::optional<T>)
{}
Run Code Online (Sandbox Code Playgroud)
即使存在从2到2的转换,也不能使用非可选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++ ×10
c++17 ×10
c++20 ×1
compile-time ×1
exception ×1
function ×1
gcc ×1
optional ×1
return-type ×1
stringstream ×1
template-argument-deduction ×1
templates ×1