小编use*_*570的帖子

std::type_identity 支持多个可变参数列表

std::type_identity可用于提供不可推论的上下文。所以,我想知道它是否适用于推导的可变参数列表。但不同的编译器给出不同的结果。
https://godbolt.org/z/4cfqbxdeo

#include <type_traits>
 
struct in_between{};

template <typename... T>
struct args_tag
{
    using type = std::common_type_t<T...>;
};

template <typename... T>
void bar(args_tag<T...>, std::type_identity_t<T>..., int, std::type_identity_t<T>...) {}

template <typename... T>
void bar(args_tag<T...>, std::type_identity_t<T>..., in_between, std::type_identity_t<T>...) {}

// example
int main() {
    bar(args_tag<int, int>{}, 4, 8, 15, 16, 23);
    bar(args_tag<int, int>{}, 4, 8, in_between{}, 16, 23);
}
Run Code Online (Sandbox Code Playgroud)

第一个使用 gcc 和 msvc 编译。

bar(args_tag<int, int>{}, 4, 8, 15, 16, 23);
Run Code Online (Sandbox Code Playgroud)

第二个只能用 msvc 编译。

bar(args_tag<int, int>{}, 4, 8, in_between{}, 16, 23);
Run Code Online (Sandbox Code Playgroud)

根据标准,行为应该是什么?

c++ templates language-lawyer c++20 parameter-pack

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

const_cast UB:澄清引用与对象/值

我知道这是未定义的行为(这里已经有其他问题在谈论这种情况):

int const i = 0;
int const& j = i;
const_cast<int&>(j) = 8;
Run Code Online (Sandbox Code Playgroud)

不过,我想这不是吧?

int i = 0;
int const& j = i;
const_cast<int&>(j) = 8;
Run Code Online (Sandbox Code Playgroud)

如果我没记错的话,UB 只修改const对象,而不管您用来引用它的引用的限定符如何。因此,删除对最初不是 const 的对象的引用的 const 限定符,然后写入它就可以了,对吗?

c++

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

为什么在使用 clang 进行静态声明时,alignas 无法编译?

我在 clang 上遇到编译错误,并使用以下代码对 gcc 发出警告:

static alignas(16) int one_s = 1;                      // clang: error: an attribute list cannot appear here; gcc: warning: attribute ignored;
static __attribute__((aligned(16))) int zero_s = 0;    // on the other hand this works well on both compilers...
alignas(16) int one = 1;                               // this also works on both compilers
__attribute__((aligned(16))) int zero = 0;             // as well as this
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么在包含 static 关键字的声明中不接受alignas?我将 --std=c++11 编译器选项与 gcc 和 clang 一起使用。(编辑:我使用 clang 3.4 及更高版本和 gcc 4.8 及更高版本)

请注意,使用 Visual …

c++ static clang language-lawyer alignas

5
推荐指数
1
解决办法
1304
查看次数

C++ 中一系列模板参数的显式模板实例化

创建库时,显式模板实例化非常有用。假设我有一个带有 int 参数的模板:

template <int i> struct S { ... };
Run Code Online (Sandbox Code Playgroud)

要执行显式模板实例化,语法类似于

template struct S<1>;
Run Code Online (Sandbox Code Playgroud)

但是,我只能以这种方式使用一行实例化一个实例。我想做的是以一种优雅的方式定义一系列模板。例如,考虑无法编译的错误代码:

#define MIN_I 1
#define MAX_I 16
for (int i = MIN_I; i <= MAX_I; i++) // i should be a constant
    template struct S<i>;
Run Code Online (Sandbox Code Playgroud)

这样,当MAX_I改变时,修改就非常简单了。我能实现这个目标吗?如果可能的话,有没有一种简单的方法可以做到这一点?谢谢你!

此外,这个问题可以推广到更一般的环境。例如,我可以采用 1,2,4,8,16,32,64,128,256 或一些预定义的序列。

我创建模板库的原因不好说。简而言之,我将创建一个在GPU上运行的CUDA库(由nvcc编译器编译),并由gcc编译的标准c++程序调用。

c++ templates

5
推荐指数
1
解决办法
1218
查看次数

强制转换为 void 以避免使用重载的用户定义逗号运算符

void我正在学习 C++ 中的模板,并遇到了一个使用强制转换的示例:

template<typename T>
auto func (T const& t) -> decltype( (void)(t.size()), T::size_type() )
{
return t.size();

}
Run Code Online (Sandbox Code Playgroud)

解释中写道:

将表达式强制转换为 void 是为了避免用户定义的逗号运算符针对表达式类型重载的可能性。

我的问题是:

  1. 如何使用强制转换为 void 来“避免用户定义的逗号运算符重载表达式类型的可能性”?我的意思是,任何人都可以举出任何例子,如果我们不使用void此代码会给出错误吗?例如,假设我们有一个名为 的类SomeClass,它重载了逗号运算符。现在,如果我们不使用,这会成为问题吗void

  2. static_cast在这种情况下可以使用 C 风格的强制转换吗?例如,类似的东西static_cast<void>(t.size())。我正在阅读使用 C++17 功能的示例,因此我想知道为什么作者在这种情况下使用了 C 风格转换。

我读过强制转换为“void”到底有什么作用?,从中我得到的印象是,如果我们使用(void)xthen 这意味着抑制编译器警告,并且还意味着“忽略 x 的值”。但后来我无法理解表达式x和之间的区别(void)x

c++ casting void c++11 c++17

5
推荐指数
1
解决办法
262
查看次数

返回对本地 int 变量的引用始终是未定义的行为

我读到我们不应该返回局部变量的指针或引用。因此,在下面给出的示例中,我知道当我编写:return i;inside function时foo,我返回对局部变量的引用。在函数外部使用该引用将导致未定义的行为。

#include <iostream>

const int& foo()
{
    int i = 5;
    return i;//returning reference to a local variable
}

const int& func()
{
    return 5;
}

int main()
{
    const int& ref = func();
    const int& f = foo();
    std::cout<<f<<std::endl; //I know this is undefined behavior because we're using a reference that points to a local variable 
    std::cout<<ref; //But IS THIS UNDEFINED BEHAVIOR too?
}
Run Code Online (Sandbox Code Playgroud)

return 5;我的问题是,对于function 内部的return 语句是否同样适用func。我知道在 C++17 中存在强制复制 …

c++ reference function local

5
推荐指数
1
解决办法
390
查看次数

构造函数在 C++ 中是否具有“类型”,因为它是一个特殊的成员函数

我最近了解到构造函数在 C++ 中没有名称以及有关它们的其他一些信息。我还知道函数在 C++ 中有一种称为函数类型的类型。例如,

void func(int)
{
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中, 的函数类型func为。 void (int)

现在,我想知道,由于构造函数是特殊的成员函数,那么它们是否也具有如上所示的类型。例如说我们有:

struct Name
{ 
    Name(int)
    {
    }
};
Run Code Online (Sandbox Code Playgroud)

上面所示的构造函数是否也像普通函数或普通成员函数一样具有函数类型。如果是,那么我们如何找到该类型。就像我们可以decltype在普通函数上使用一样,是否允许decltype在构造函数上使用来查找它们的类型。

c++ constructor types function language-lawyer

5
推荐指数
1
解决办法
183
查看次数

this 指针不能在构造函数中使用别名:

我正在学习 C++ 中的继承。我发现了以下声明

换句话说,this 指针不能在构造函数中使用别名:

extern struct D d;
struct D
{
    D(int a) : a(a), b(d.a) {} // b(a) or b(this->a) would be correct
    int a, b;
};
D d = D(1);   // because b(d.a) did not obtain a through this, d.b is now unspecified
Run Code Online (Sandbox Code Playgroud)

上面的例子来自cppreference

我的第一个问题是,它写道“this不能在 ctor 中使用别名”,但在上面的示例中,他们在注释中写道“b(this->a)将是正确的”。这对我来说似乎是矛盾的,因为当他们说this不能在 ctor 中使用别名时,我理解“this不能在 ctor 中使用”。但为什么他们说如果不能在 actor 中使用/别名,那么书写b(this->a)就是正确的。this初始化列表不被认为是“在一个ctor中”吗?


现在让我们看一个自定义示例:

struct Name 
{ …
Run Code Online (Sandbox Code Playgroud)

c++ class this language-lawyer c++11

5
推荐指数
1
解决办法
139
查看次数

构造函数是否也有隐式 this 参数

我正在学习 C++ 中的类,并且知道非静态成员函数具有隐式 this 参数。我的第一个问题是构造函数是否也有一个隐式的 this 参数,就像非静态成员函数一样。请注意,我并不是问我们是否可以this在 ctor 内部使用,因为我已经知道我们可以this在 ctor 内部使用。


接下来,我知道在const类的合格非静态成员函数内X, 的类型thisconst X*。对于非静态成员函数(没有 const 限定), 的类型thisX*。同样,在 ctor 内部, 的类型this始终是X*。更深层次的问题来了。

我们知道,当我们调用一个非静态成员函数(例如obj.func())时,名为的对象的地址obj会隐式传递给方法的隐式 this 参数func。所以这解释了“this非静态成员函数的来源”。

现在,让我们将同样的事情应用于构造函数。例如,假设我们X使用默认 ctor 创建一个类的对象,如下所示:

X x; //does the default ctor also have an implicit this parameter to which the address of x is passed? …
Run Code Online (Sandbox Code Playgroud)

c++ constructor this language-lawyer

5
推荐指数
1
解决办法
411
查看次数

MSVC 与 GCC 和 Clang 使用 lambda 时的错误

我正在尝试CppCon上展示的一个使用lambdas的示例。令我惊讶的是,该程序不在 gcc 和 clang 中编译(在 C++14 或 C++17 中),而是在 msvc 中编译。这可以在这里得到验证。

作为参考,示例代码如下:

#include <stdio.h>

int g = 10;
auto kitten = [=]() { return g+1; };
auto cat = [g=g]() { return g+1; };

int main() {
    g = 20;
    printf("%d %d\n", kitten(), cat());
}
Run Code Online (Sandbox Code Playgroud)

这里有什么问题(如果有的话)以及哪个编译器是正确的?

请注意,该代码是从他们的官方演示幻灯片中精确复制粘贴的。

c++ lambda language-lawyer

5
推荐指数
1
解决办法
591
查看次数