【问题标题】:static_assert inside a macro throwing compile time errors even when it shouldn't (Visual Studio)宏中的 static_assert 即使不应该抛出编译时错误(Visual Studio)
【发布时间】:2021-09-07 10:03:57
【问题描述】:

tl;博士

当我尝试编译此代码时,Visual Studio 会为 static_assert 抛出一个编译时错误,不管它应该是什么,然后还会为唯一应该的那个抛出一个“活动错误”。这是我的代码或 Visual Studio 的问题?

Visual Studio 版本
Microsoft Visual Studio 社区 2019
版本 16.10.2

#include <memory>

struct Node {};
struct A : Node {};
struct B : Node {};

#define cast_to_A(ptr) ([&] () { \
    static_assert( \
        std::is_same<std::shared_ptr<Node>, decltype(ptr)>::value, \
        "Cannot cast to an A pointer." \
    ); \
    return std::static_pointer_cast<A>(ptr); \
})()

#define cast_to_B(ptr) ([&] () { \
    static_assert( \
        std::is_same<std::shared_ptr<Node>, decltype(ptr)>::value, \
        "Cannot cast to a B pointer." \
    ); \
    return std::static_pointer_cast<B>(ptr); \
})()

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();
    auto aAsNode = std::static_pointer_cast<Node>(a);
    auto bAsNode = std::static_pointer_cast<Node>(b);

    auto a1 = cast_to_A(aAsNode); // Expected: No error, Actual: "Cannot cast to an A pointer."
    auto b1 = cast_to_B(bAsNode); // Expected: No error, Actual: "Cannot cast to an B pointer."

    auto badCast = cast_to_A(b); // Expected & Actual: "Cannot cast to an A pointer."

    return 0;
}

上下文

在一个个人项目中,我有一个 node 结构,一堆子结构从中继承。在整个程序中,我从std::shared_ptr&lt;Node&gt; 转换为std::shared_ptr&lt;Child&gt;,反之亦然,使用std::static_pointer_cast。在我的程序的某个地方,我有编译时错误,我正试图从一个兄弟指针转换为另一个。但是,该错误归因于 std::static_pointer_cast 的第 1925 行)中的代码,并且由于它不是运行时错误,因此我无法向上移动调用堆栈以查找错误调用的位置。

碰巧的是,我的结构代码是由我编写的 python 脚本程序生成的。我尝试的解决方案是为每个结构生成一个宏(就像在玩具示例中看到的那样),然后我只是做了一个正则表达式搜索/替换,用适当的宏替换我所有的 std::static_pointer_cast 调用。

我遇到的问题是在上面的玩具示例中重新创建的。 Visual Studio 在宏“调用”下放了一条红线,我预计会失败(所以我现在实际上发现了这个错误),但是对于宏的每次使用它也会从 static_assert 引发编译时错误,即使(据我所知)它不应该失败。不过,它并没有在这些“调用”下添加红线,所以我不确定这是否是 Visual Studio 错误。

在网上环顾四周,std::is_same 可以非常挑剔什么算作同一类型。作为 marco 参数给出的变量 get 通过引用传递给 static_assert (因为它通过 lambda 的 [&amp;] 捕获),所以我想知道这是否把它扔掉了。但是我想不出任何方法来调整类型以使其正常工作。

提前感谢您的帮助!非常感谢任何指针或提示!

【问题讨论】:

  • 由于您通过引用将参数传递给 lambda,我认为您可能需要使用 remove_reference, decltype(std::remove_reference(ptr))
  • @1201ProgramAlarm 你说得对!语法略有不同,但我让它工作了,现在只有糟糕的演员才会抛出错误。语法是std::remove_reference&lt;decltype(ptr)&gt;::type。非常感谢您的帮助!

标签: c++ visual-studio compiler-errors macros static-assert


【解决方案1】:

@1201ProgramAlarm 在 cmets 中回答。解决方案是使用std::remove_reference 删除在传递到 lambda 时添加到 ptr 的引用。最后的宏是:

#define cast_to_A(ptr) ([&] () { \
    static_assert( \
        std::is_same<std::shared_ptr<Node>, std::remove_reference<decltype(ptr)>::type>::value, \
        "Cannot cast to an A pointer." \
    ); \
    return std::static_pointer_cast<A>(ptr); \
})()

现在只有预期的“bad cast”会引发错误

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-19
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    相关资源
    最近更新 更多