【问题标题】:Is there a workaround for this C4702 link-time warning?此 C4702 链接时警告是否有解决方法?
【发布时间】:2011-04-01 11:10:50
【问题描述】:

我正在使用 boost::variant 并且在发布模式下编译时遇到问题。我在 VC2010 中工作,警告级别为 4,警告为错误。下面的代码在调试模式下编译良好,但在发布模式下,我在链接时收到一堆“无法访问的代码”C4702 警告(大概我在这里收到编译器警告,因为启用优化时会生成链接时代码。)

是否有人在这种情况下成功禁用了这些警告?如果可能的话,我宁愿保持高警告级别和警告作为错误。

#pragma warning( disable:4702 )

... 在这里似乎不起作用。下面是一些示例代码:

#include <boost/variant.hpp>

struct null{};
typedef boost::variant< null, double > variant_t;

class addition_visitor
: public boost::static_visitor< variant_t >
{
public:
    template< typename T, typename U >
    variant_t operator()( const T&, const U& ) const
    { 
        throw( "Bad types" );
    }

    variant_t operator()( const double& left, const double& right ) const
    {
        return variant_t( left * right );
    }
};

int main(int /*argc*/, char** /*argv*/)
{
    variant_t a( 3.0 ), b( 2.0 );
    variant_t c = boost::apply_visitor( addition_visitor(), a, b );
    return 0;
}

警告是由模板化的 operator() 触发的,我用它来捕获试图将访问者应用于错误的变体类型的尝试。

【问题讨论】:

  • 对警告级别 4 + 警告为错误点赞!
  • 您是否尝试将编译指示放在文件顶部,在包含之前?而且@Matthieu 绝对会在漏洞出现之前将其杀死。
  • 我尝试将编译指示放在文件顶部、类定义周围、apply_visitor 调用周围以及stdafx.h 的顶部。不幸的是,这些似乎都不起作用。
  • 这很奇怪。我可以在没有#pragma warning( disable:4702 ) 的情况下重现警告,但只要我把它放在那里(在第一个#include &lt;boost/variant.hpp&gt; 之前的任何地方)它就会消失。除了 /W4 和 /WX 之外,您还使用任何其他非标准设置吗?我尝试了使用和不使用 LTCG,没有区别,只是有效。您是否安装了 SP1?因为我没有。
  • 这个解决方案在 VS2010 中对我有用:stackoverflow.com/questions/12380603/…

标签: c++ visual-studio-2010 compiler-warnings suppress-warnings


【解决方案1】:

吃了一顿午餐和散步后,我有一个不满意但有效的解决方法。我没有从访问者那里返回一个变体并引发错误,而是返回一个成功布尔值并存储一个结果,因此:

#include <boost/variant.hpp>

struct null{};
typedef boost::variant< null, double > variant_t;

class addition_visitor
: public boost::static_visitor< bool >
{
public:
    template< typename T, typename U >
    bool operator()( const T&, const U& )
    { 
        //throw( "Bad types" );
        return false;
    }

    bool operator()( const double& left, const double& right )
    {
        result = variant_t( left * right );
        return true;
    }

    variant_t result;
};

int main(int /*argc*/, char** /*argv*/)
{
    variant_t a( 3.0 ), b( 2.0 );
    addition_visitor v;
    if( !boost::apply_visitor( v, a, b ) )
    {
        throw( "Bad types" );
    }

    variant_t c = v.result;
    return 0;
}

【讨论】:

    【解决方案2】:

    为什么要为模板操作符提供一个主体?

    我这里没有方便的 Boost,所以我不能帮你检查,但是模板化运算符有一个主体这一事实很可能意味着任何和所有调用,无论类型如何,都可以正常编译,然后抛出一个运行时出错。

    将模板运算符的主体排除在外,当与除 double 之外的任何其他类型一起使用时,它将简单地拒绝链接。

    【讨论】:

    • 问题是变体的类型是在运行时确定的。在这种情况下,变量实际上保存了来自市场数据流的值,并且值的选择(以及它们的类型)是可配置的。例如,这个访问者类可能应用于包含 null 和 double 的变体,我需要捕获它。编译器期望变体模板参数列表中的每对类型都有一个有效的 operator() ;如果我声明了非双精度方法但不提供实现,则会收到“未解决的外部”链接器错误。
    【解决方案3】:

    #pragma 不起作用,因为这是链接时间而不是编译时间警告。

    您可以在发布模式下抑制警告。我相信链接器命令行上的 /ignore:xxxx 可以解决问题。

    【讨论】:

    • 不幸的是,忽略链接器错误的选项已从 VC2010 中删除。此外,这实际上是一个编译器警告,由链接时代码生成(我估计)生成。
    【解决方案4】:

    我在 Visual Studio 2012 MFC 项目中遇到了非常相似的问题;同样的警告来自 头文件,也在 Release 链接时间代码生成期间。
    我通过在预编译的头文件中添加 #pragma warning(disable:4702) 解决了这个问题(在我的例子中是 "stdafx.h",就在 之前#包括 STL 头文件)。

    【讨论】:

      【解决方案5】:

      如果我声明了非双精度方法但是 不提供实现然后我 获取“未解析的外部”链接器 错误。

      尝试在模板运算符定义中添加inline 说明符。那么 MSVC 不应该需要它的主体来编译类本身。因此,只有当您的代码尝试使用此模板时,您才会收到编译时错误,而不是 unresolved external。据我了解 - 这正是您想要的。

      【讨论】:

      • 您可能被我的简化示例代码误导了。实际上,我在编译时不知道我的变体的类型。它们包含来自实时提要的价格,其中一些可能是双倍的,一些可能是空的。类型检查是在运行时进行的,所以在编译时我需要(boost::variant 实现,因此编译器需要)visitor 方法的实现,用于包含类型的所有可能组合。
      【解决方案6】:

      将模板化的operator()(...) 设为私有并且不提供实现。这将在编译时而不是链接时捕获它的使用。

      【讨论】:

      • 变体类型检查是在运行时进行的(请参阅我的 cmets 并在其他地方回答),因此无法提供实现是行不通的。
      猜你喜欢
      • 2013-10-27
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      • 2020-04-07
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      相关资源
      最近更新 更多