【问题标题】:Clang does not allow static_cast to parent class with template, while g++ and icc allowClang 不允许 static_cast 到带有模板的父类,而 g++ 和 icc 允许
【发布时间】:2013-06-22 22:34:36
【问题描述】:

我正在尝试我的 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 存储库)、Intel 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 扩展支持?还是未定义的行为?

【问题讨论】:

  • 我认为(但不确定)V 在其成员的声明符(包括尾随返回类型)中不完整,因此不允许对其基类进行 static_cast,因为它需要一个完整的类型。我更确定它不完整的事实然后关于这不允许演员表。
  • 你可以试试*static_cast&lt;std::valarray&lt;T&gt;*&gt;(this)
  • 或者直接使用decltype(begin(valarray&lt;T&gt;()))
  • 这并不能回答您的问题,但clang 似乎更喜欢*static_cast&lt;std::valarray&lt;T&gt;*&gt;(nullptr) 的更常见使用模式
  • 我不明白为什么它需要一个完整的类型。可以将不完整的类型传递给引用参数(复制或移动构造函数)。

标签: c++11 g++ clang static-cast


【解决方案1】:

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

您正在对值类型执行static_cast,而不是引用或指针。这会创建一个新的临时 valarray 对象,因此会调用 beginconst 重载(可能不是您想要的),并且 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,它只需要知道在 valarray&lt;T&gt; 上调用 std::begin 的类型,因此类型是否不完整并不重要,因为你没有'不需要演员表。

在函数体中,类型被认为是完整的,所以强制转换是有效的。

【讨论】:

    猜你喜欢
    • 2019-11-20
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多