【问题标题】:How to get rid of C4800 warning produced by boost::flyweight in VS2008如何摆脱 VS2008 中 boost::flyweight 产生的 C4800 警告
【发布时间】:2009-10-08 11:14:38
【问题描述】:

在打开 MFC 的 VS2008 中编译以下代码时,我收到警告。提升版本 1.39


include "boost/flyweight.hpp"
include "boost/flyweight/key_value.hpp"
class Foo
{
  public:
    Foo(const CString& item) : mfoo(item) {}
    const CString& getkeyvalue() const {return mfoo;}
  private:
    const CString mfoo;
};
struct Conversion
{
  const CString& operator() (const Foo& item) const {return item.getkeyvalue();}
};  

using namespace boost::flyweights;
flyweight<key_value<CString, Foo, Conversion>, tag<Foo> > flyweight_test;

上面代码的最后一行产生了一个警告

d:\work\sourcecode\boost1390\boost\functional\hash\extensions.hpp(72):警告 C4800:'const wchar_t *':强制值为 bool 'true' 或 'false'(性能警告)
d:\work\sourcecode\boost1390\boost\functional\hash\extensions.hpp(71) : 在编译类模板成员函数size_t boost::hash&lt;T&gt;::operator ()(const T &amp;) const 时使用
[
T=ATL::CStringT&lt;wchar_t,StrTraitMFC_DLL&lt;wchar_t&gt;&gt;
]
d:\work\sourcecode\boost1390\boost\multi_index\hashedindex.hpp(1159) :请参阅使用
编译的类模板实例化 'boost::hash' 的参考 [
T=ATL::CStringT&lt;wchar_t,StrTraitMFC_DLL&lt;wchar_t&gt;&gt;
]

此警告通过散列工厂、MPL 等持续不断。

为什么会出现警告以及如何更正代码以不产生警告?

编辑:
要修复,请在下面添加 hash_value 的实现


template<typename CharType, typename TraitsType>
std::size_t hash_value(const ATL::CStringT<CharType, TraitsType>& s)
{
    return CStringElementTraits<typename TraitsType>::Hash(s);
}

【问题讨论】:

  • 我的代码中有一次类似的警告。当我尝试使用 const char* (或在您的情况下为 const wchar_t* )调用模板化函数并且可以使用多个重载时,就发生了这种情况。我想要隐式转换为字符串,但编译器选择了转换为 bool。
  • 我想知道它是否有助于使用 GCC 进行编译,我记得我非常明确地指出了问题的来源?还是使用 MFC 完全不可行?还是 GCC 没有给出这个警告?

标签: c++ mfc boost compiler-warnings


【解决方案1】:

我使用 /Wall 进行编译,这会导致 Boost 生成各种警告。此外,我指示编译器将所有警告都视为错误,因此根本不需要警告。

为了避免在编译 Boost 标头时收到任何警告,我使用 #pragma warning 将警告级别暂时降低到尽可能低,并在处理 Boost 标头时关闭任何剩余的警告:

// 设置最小警告级别 #pragma 警告(推,0) // 在这个级别仍然会出现一些警告 // 如有必要,禁用先前 pragma 未涵盖的特定警告 #pragma 警告(禁用:4800) #包括 // 恢复警告级别 #pragma 警告(弹出)

这可以确保我的代码在编译时使用了最高级别的错误检查,而我无法控制的代码仍然可以成功编译。

我能看到的唯一其他选择是忽略警告或维护 Boost 代码的修补版本,直到这些警告得到修复,这两种方法都不是很吸引人。

【讨论】:

  • 我并不是真的要禁用警告。无论如何感谢您的建议。
【解决方案2】:

当编译器必须将 int 表达式转换为 bool 时,会发出 C4800 警告。

例如:

int k = 11;
bool f()
{ return k; }

int 表达式 k, 由

的内部定义转化而来
k == 0 => *false*
k != 0 => *true*

bool的定义

b == false (internally == 0) => *false*
b == true  (internally == 1) => *true*

因为在 C++ 中任何值(除 0 以外)都可能表示 true,因此编译器必须将 k 转换为 bool。

正如警告正确指出的那样,这种转换可能会影响性能。

注意:这个警告可能有点多余,因为编译器通常会从代码中提取正确的含义,并将其优化掉。

编译器将从我的示例代码创建的伪 C 代码:

char f()
{
    if( k )
       return (char) 1;
    return (char) 0;
}

【讨论】:

  • 谢谢,我正在寻找关于 C4800 有多糟糕的解释,但没有找到任何地方!
【解决方案3】:

享元中的一个类可能使用 hash_value 函数(或包装类哈希)从 ATL::CString 计算哈希值。这不是直接在 boost 中定义的,因此您需要提供一个实现:

std::size_t hash_value(const ATL::CString& s)
{
     // ...
}

只看你的编译器输出,似乎 CString 本身是模板化的,所以你会实现

template<typename CharType, typename TraitsType>
std::size_t hash_value(const ATL::CString<CharType, TraitsType>& s)
{
     // calculate hash e.g. by calling hash_value(const std::string&)
}

【讨论】:

  • 伟大的领导。实际上,hash_value 是基于 bool 生成的。在这种情况下完全不正确。原始问题中提供的实现。
【解决方案4】:

我不知道如何纠正该警告,但您可以通过将以下代码添加到您的 cpp 文件来关闭它:

#pragma warning(disable:4800)

查看MSDN 以获取更多参考。

【讨论】:

  • 不希望禁用警告。这是题外话。
【解决方案5】:

警告的来源不在您的代码中。您必须修复有问题的 Boost 代码。

【讨论】:

  • 没有帮助。使用模板,虽然它可能是给出编译警告/错误的扩展代码,但根本原因可能在应用程序代码中
猜你喜欢
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
  • 2010-09-21
相关资源
最近更新 更多