gpt4 book ai didi

c++11 - Clang 不允许 static_cast 到带有模板的父类,而 g++ 和 icc 允许

转载 作者:行者123 更新时间:2023-12-01 06:33:43 25 4
gpt4 key购买 nike

我正在尝试我的 C++11 代码,看看是否所有最近的主要编译器都支持我使用的功能,以及以下缩短的代码

#include <valarray>

struct T
{
double vv[3];
};

class V : public std::valarray<T>
{
public:
auto begin()->decltype(std::begin(static_cast<std::valarray<T>>(*this)))
{
return std::begin(static_cast<std::valarray<T>>(*this));
}
};

int main(void)
{

}

将使用 g++ 4.8.1(来自 Debian sid 存储库)、英特尔 C++ 编译器 13.1.1 20130313,而不是 Clang 3.3-2(来自 Debian sid 存储库)进行编译。

给定的错误是:
test.cpp:11:73: error: no viable conversion from 'V' to 'std::valarray<T>'
auto begin()->decltype(std::begin(static_cast<std::valarray<T>>(*this)))
^~~~~

但是,像这样的代码
namespace std
{
auto begin(V& vv) -> decltype(std::begin(static_cast<V::parent_t>(vv)))
{
return std::begin(static_cast<V::parent_t>(vv));
}
}

将由所有三个编译器编译。

我的问题是:代码本身是否被语言标准所允许,只是 Clang 错误编译了它,还是仅由 g++/icc 扩展支持?或者它是未定义的行为?

最佳答案

代码非常危险,即使对于 GCC 和 ICC 也需要修复。

你正在做一个 static_cast到值类型,而不是引用或指针。这会创建一个新的临时 valarray对象,所以 const begin 过载被调用(可能不是你想要的),迭代器返回 begin()引用立即超出范围的临时对象,因此返回的迭代器无效,取消引用它是未定义的行为。

代码将像这样编译:

    auto begin()->decltype(std::begin(std::declval<std::valarray<T>&>()))
{
return std::begin(static_cast<std::valarray<T>&>(*this));
/* cast to reference type! ^^^^^^^^^^^^^^^^^ */
}
decltype不需要投 this ,它只需要知道调用的类型 std::beginvalarray<T> ,因此类型是否不完整并不重要,因为您不需要强制转换。

在函数体中,该类型无论如何都被认为是完整的,因此转换是有效的。

关于c++11 - Clang 不允许 static_cast 到带有模板的父类,而 g++ 和 icc 允许,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17309033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com