小编Pas*_* By的帖子

T * ...和const T&的部分排序

cppreference要求以下内容

template <class ...T> int f(T*...);  // #1
template <class T>  int f(const T&); // #2
f((int*)0); // OK: selects #1
            // (was ambiguous before DR1395 because deduction failed in both directions)
Run Code Online (Sandbox Code Playgroud)

如果我们遵循DR1395,我们将看到

如果A是从函数参数包转换而P不是参数包,则类型推导失败。否则,使用 使用所得到的类型的P和A,扣然后作为在17.9.2.5 [temp.deduct.type]描述的方法进行。如果P是函数参数包,则将参数模板的每个其余参数类型的类型A与函数参数包的声明符ID的类型P进行比较。每次比较都会为模板参数包中由功能参数包扩展的后续位置推导模板参数。同样,如果A是从功能参数包转换而来的,则将其与参数模板的每个其余参数类型进行比较。 如果对给定类型成功推导,则认为参数模板中的类型至少与参数模板中的类型一样特殊。

[...]

在考虑上述因素后,如果功能模板F至少与功能模板G一样专门,反之亦然,并且G的尾随参数包中F没有对应的参数,并且F没尾随参数包,则F比G更专业。

根据我的推断,这意味着我们应该匹配从T*...const T&反之亦然的每个单独类型。在这种情况下,T*它比const T&TU*成功,T*U失败)更加专业。

但是,编译器不同意。Clang认为它是模棱两可的,gcc认为应该调用第二个,两者都与cppreference不同。

正确的行为是什么?

c++ language-lawyer

15
推荐指数
1
解决办法
1060
查看次数

函数指针是否在调用时使用

这个问题是由意见引起这里

请考虑以下代码

template <typename T, typename C>
void g(T, C) {}

template <typename T, typename C>
struct G
{ 
    static constexpr void (*m) (T, C) = &g; 
}; 

void foo()
{
    auto l = [](int){return 42;};
    G<int, decltype(l)>::m(420, l);
}
Run Code Online (Sandbox Code Playgroud)

这在C++ 17中是合法的,通过内联变量和所有这些G::m来定义G.

有什么奇怪的是在C++ 14和C++ 11 gcc拒绝这个说明m被使用但从未定义,而clang接受它.生活

是否使用了modr?或者这是一个gcc bug?

c++ language-lawyer

14
推荐指数
1
解决办法
459
查看次数

什么是具有静态存储持续时间的临时对象

灵感来自这个答案,来自[expr.const]

常量表达式是glvalue核心常量表达式,它指的是一个实体,它是常量表达式的允许结果(如下所定义),或者是一个prvalue核心常量表达式,其值满足以下约束:

  • 如果值是类类型的对象,则引用类型的每个非静态数据成员引用一个实体,该实体是常量表达式的允许结果,

  • 如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象末尾的地址([expr.add]),函数的地址或空指针值,以及

  • 如果值是类或数组类型的对象,则每个子对象都满足这些值的约束.

如果实体是具有静态存储持续时间对象,则该实体是常量表达式的允许结果,该对象不是临时对象,或者是其值满足上述约束的临时对象,或者它是函数.

什么是具有静态存储持续时间的临时对象?我是否遗漏了某些东西,或者说对象是暂时的并且具有静态存储持续时间是矛盾的吗?

来自[basic.stc.static]的定义

所有没有动态存储持续时间,没有线程存储持续时间且不是本地的变量都具有静态存储持续时间.这些实体的存储应持续该计划的持续时间

仅适用于变量.

c++ language-lawyer

13
推荐指数
1
解决办法
546
查看次数

是否允许在decltype(自动)变量上使用cv限定符?

该标准规定了这一点

如果占位符是decltype(auto)类型说明符,T则应仅为占位符.

decltype(auto)*x7d = &i; //错误,声明的类型不明白 decltype(auto)

目前尚不清楚是否仍然允许使用cv-qualifiers.如果他们被允许将是有道理的.编译器似乎在这个问题上存在分歧.以下代码被g ++接受被clang ++拒绝,vc ++似乎根本不支持decltype(auto)变量:

int main()
{
    const decltype(auto) sz_text{"test"};
}
Run Code Online (Sandbox Code Playgroud)

c++ decltype language-lawyer auto c++17

13
推荐指数
1
解决办法
405
查看次数

如果没有发生左值到右值转换,则取消引用无效指针是合法的

尽我所能,我见过的最接近的答案就是这个,有两个完全相反的答案(!)

问题很简单,这是合法的吗?

auto p = reinterpret_cast<int*>(0xbadface);
*p;  // legal?
Run Code Online (Sandbox Code Playgroud)

我对此事的看法

  1. 将整数转换为指针:对可以转换的内容没有限制
  2. 间接:仅表示结果是左值.
  3. 生命周期:只说明对象无法做到的事情,这里没有任何对象
  4. 表达式语句:*p是一个废弃的值表达式
  5. 丢弃值表达式:不进行左值到右值转换
  6. lvalues的未定义:也就是严格别名规则,只有当左值转换为右值时

所以我得出结论,没有明确说明这是未定义的行为.然而,我清楚地记得一些平台陷入间接无效指针.我的推理出了什么问题?

c++ language-lawyer

12
推荐指数
1
解决办法
391
查看次数

关于std :: string移动的实现

我正在调查搬家的表现std::string.在最长的时间里,我认为字符串移动几乎是免费的,认为编译器将内联所有内容,它只涉及一些廉价的任务.

事实上,我的移动心理模型是字面上的

string& operator=(string&& rhs) noexcept
{
    swap(*this, rhs);
    return *this;
}

friend void swap(string& x, string& y) noexcept
{
    // for disposition only
    unsigned char buf[sizeof(string)];
    memcpy(buf, &x, sizeof(string));
    memcpy(&x, &y, sizeof(string));
    memcpy(&y, buf, sizeof(string));
}
Run Code Online (Sandbox Code Playgroud)

据我所知,如果将memcpy其更改为分配单个字段,则这是一个合法的实现.

我非常惊讶地发现gcc的移动实现涉及创建一个新的字符串,并且可能因为分配而可能抛出noexcept.

这甚至符合要求吗?同样重要的是,我不应该认为移动几乎是免费的吗?


令人眼花缭乱,std::vector<char>归结为我所期待的.

clang的实现有很大的不同,尽管存在疑问std::string::reserve

c++ string move-semantics

12
推荐指数
1
解决办法
291
查看次数

要求包含<initializer_list>的理由是什么?

来自[dcl.init.list]

模板std?::?initializer_­list未预定义; 如果在使用之前未包含标题std?::?initializer_­list- 即使是未命名类型的隐式用法 - 程序也是格式错误的.

既然std?::?initializer_­list编译器是特殊的,那么为什么它不被视为语言的一流语法?

我对一些可能性及其反驳的看法:

命名空间污染

可以解决就像std::size_t,包含头只引入标识符.

注意,auto sz = sizeof(0);即使没有包含任何标题,如何形成良好,而不是auto il = {1, 2, 3};形成错误.

编译开销

libstdc ++实现的std::initializer_list字面数小于50行,不依赖于其他标头.这有多大的开销?

c++

11
推荐指数
1
解决办法
164
查看次数

在Windows上使用clang编译CUDA时的重新定义

尽管已经提出了一个几乎完全相同的问题,但答案是针对OSX并且不再适用(反正真的是hacky).

问题是当在窗口上用clang编译cuda时,有大量的重新定义math_functions.hpp.

随着一些调查,显然CUDA决定把它math_functions.hppmath_functions.h功能namespace std(这是甚至合法的吗?),并在所有的libstdc ++函数相撞cmath和铛自己的编译CUDA头.

我该如何处理?最好不要使用上一个问题中显示的hacky方式?

边注

根据clang的文档,clang可以基于__global__/ __device__限定符重载,代码不应该只编译吗?

细节

版本:
铿锵4.0.0(建立像这样)
的libstdc ++从GCC 7.1.0来
CUDA 8.0
窗口10

完整的错误输出

clang++ hellocuda.cu  --cuda-path=E:\cuda\development --cuda-gpu-arch=sm_20 -LE:\cuda\development\lib\x64 -lcudart_static -ldl -lrt -std=c++1y -O2 -pedantic -Wall -Wextra -fms-extensions -o program.exe
In file included from <built-in>:1:
In file included from E:\LLVM\bin\..\lib\clang\4.0.0\include\__clang_cuda_runtime_wrapper.h:191:
E:\cuda\development/include\math_functions.hpp:1684:14: error: redefinition of
      '__isnan'
__func__(int __isnan(double a))
             ^
E:\TDM-GCC\mingw64 7.1.0\mingw64\x86_64-w64-mingw32\include\math.h:525:28: note:
      previous definition is here …
Run Code Online (Sandbox Code Playgroud)

c++ cuda clang++

10
推荐指数
1
解决办法
526
查看次数

是否允许编译器评估静态断言中的重言式

提供static_assert模板通常很有帮助.在模板不应该以某种方式实例化的情况下,我经常这样做

template<typename T, typename = void>
struct S
{
    static_assert(false, "Unconditional error");
    static_assert(sizeof(T) != sizeof(T), "Error on instantiation");
};

template<typename T>
struct S<T, std::enable_if_t<std::is_integral_v<T>>>
{
    // ...
};
Run Code Online (Sandbox Code Playgroud)

static_assert即使没有实例化,第一个将立即失败S,而如果没有实例化将导致主模板,第二个将成功.

第二个static_assert显然是一个重言式,但它"取决于" T,以达到预期的效果.但这有保证吗?是否允许编译器评估这些重言式?

c++ static-assert language-lawyer

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

标准定义了volatile变量可以改变的位置?

标准定义了哪个volatile变量可以不被检测到?

我发现了两个关于volatile的规范性文本:

intro.execution/7:

读取由volatile glvalue([basic.lval])指定的对象,修改对象,调用库I/O函数或调用执行任何这些操作的函数都是副作用,这些都是状态的变化.执行环境.表达式(或子表达式)的评估通常包括值计算(包括确定用于glvalue评估的对象的身份以及获取先前分配给用于prvalue评估的对象的值)和启动副作用.当对库I/O函数的调用返回或通过volatile glvalue进行访问时,即使调用所隐含的某些外部操作(例如I/O本身)或易失性访问,也会认为副作用已完成可能尚未完成.

这段是关于未被发现的变化吗?请问副作用这个意思?


或者有dcl.type.cv/5:

通过volatile glvalue进行访问的语义是实现定义的.如果尝试通过使用非易失性glvalue访问使用volatile限定类型定义的对象,则行为未定义.

这个段落是关于我的问题吗?什么"通过volatile glvalue进行访问的语义是实现定义的"究竟是什么意思?你能举一个不同的"访问语义"的例子吗?


还有dcl.type.cv/6,这是关于我的问题,但它只是一个注释:

[注意:volatile是对实现的暗示,以避免涉及对象的激进优化,因为对象的值可能会被实现无法检测到的方式更改.此外,对于某些实现,volatile可能指示访问对象需要特殊的硬件指令.有关详细语义,请参阅[intro.execution].一般来说,volatile的语义在C++中与在C中的相同. - 最后的注释]

c++ volatile language-lawyer c++17

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