【问题标题】:Warning 4244 (possible loss of data) in template class - Visual Studio 2010模板类中的警告 4244(可能丢失数据) - Visual Studio 2010
【发布时间】:2013-04-07 19:28:52
【问题描述】:

我确实有一个小问题,我想解决。

使用类模板,我使用 typeid() 检查数据类型,以便以正确的方式处理它们。


  template <typename _Ty_Id,
            typename _Ty_Value>
  class Attribute : public AttributeBase<_Ty_Id>
  {
    public: 
      Attribute() : 
        AttributeBase(_Ty_Id()),
        m_tyValue(_Ty_Value())
      {
      }

      Attribute(_Ty_Id tyId, _Ty_Value tyValue) : 
        AttributeBase(tyId),
        m_tyValue(tyValue)
      {
      }

      virtual ~Attribute() {};

      virtual  _Ty_Id    getId()    const {return m_tyId;}
      virtual  _Ty_Value getValue() const {return m_tyValue;}

      virtual void toXml(iolib::Xml& xmlFile)
      {
        std::list<std::string> listXmlData;
        std::string strTag;

        if(typeid(m_tyId) == typeid(std::string))
        {
          strTag = m_tyId;
        }
        else
        {
          strTag = core::Stringfunc::format(strTag, m_tyId, 0, 0);
        }

        listXmlData.push_back(strTag);
        listXmlData.push_back("entrytype");
        listXmlData.push_back(m_strEntryType);
        listXmlData.push_back("datatype");
        listXmlData.push_back(m_strDataType);

        std::string strValue;
        if(typeid(m_tyValue) == typeid(std::string))
        {
          #pragma warning(disable : 4244)
          strValue = m_tyValue;
          #pragma warning(default : 4244)
        }
        else if((typeid(m_tyValue) == typeid(float)) || 
                (typeid(m_tyValue) == typeid(double)))
        {
          strValue = core::Stringfunc::format(strValue, m_tyValue, 0, 3);
        }
        else
        {
          strValue = core::Stringfunc::format(strValue, m_tyValue, 0, 0);
        }

        listXmlData.push_back(strValue);
        listXmlData.push_back("/" + strTag);

        xmlFile.addElement(listXmlData);
      }


    private:
      _Ty_Value m_tyValue;
  }

模板参数是一个浮点值,将在 else if 分支中处理。但是,VS 2010 会带来警告 #4244,从 float 到 std::string 的隐式转换可能无法正常工作。

到目前为止,我在它发生的地方禁用了该警告,一切都会好起来的。但是,这当然只适用于 VS2012,并且希望将我的代码用于不同的目标。

有谁知道防止警告的更聪明的方法?


编辑

所以,现在我确实发布了课程的主要部分。

问题出在方法中:toXml(iolib::Xml& xmlFile),它将接受对我的 xml 类的引用。使用的类型 (m_tyValue) 是 Attribute 类的成员。

模板参数是:std::string 代表 m_tyId,float 代表 m_tyValue。

最好的问候, 海岸

【问题讨论】:

  • 不要使用 RTTI... 应尽可能避免使用。你的目标是什么?
  • 嗯...我认为使用 RTTI 检查类型是一个不错的方法。我想将值写入 xml 文件。因此,无论如何它都必须是一个字符串。当模板参数是浮点或整数类型时,我使用格式方法来完成这项工作。也许这也应该处理字符串(在这种情况下什么都不做?)
  • 嗯,我不是 100% 确定这一点,但依靠它从来都不是一个好方法。它会变得非常模糊。我不想让你放弃它,但为了功能,你为什么不试试你的建议呢?也许它看起来更好!?
  • 请向我们展示更多代码。在我看来,这不是处理不同模板类型参数的好方法(最好是 SSCCE)。
  • 你是说试试? (“你为什么不提出你的建议?”

标签: templates visual-c++ compiler-warnings


【解决方案1】:

注意:您不应使用以__(双下划线)或_ 和大写字母开头的名称。这些是在 C++ Std 中为“实现”[global.names] 保留的

要获得不同类型的不同行为(您在编译时知道类型),您可以使用类模板的(部分)特化:

template < typename Ty_Id >
struct toXmlHelper
{}; // provide no default implementation

template < >
struct toXmlHelper < double > // implementation in case Ty_Id == double
{
    void toXml() { /*...*/ }
};

template < >
struct toXmlHelper < std::string > // implementation in case Ty_Id == std::string
{
    void toXml() { /*...*/ }
};

您可能想要添加技术来减少代码冗余。

另一种方法是使用重载机制:

template < typename Ty_Id,
           typename Ty_Value>
class Attribute : public AttributeBase<_Ty_Id>
{
public:
    /* ... */
    virtual void toXml(iolib::Xml& xmlFile)
    {
        std::list<std::string> listXmlData;
        std::string strTag;
        /* ... */
        toXmlHelper(m_tyId);
    }
private:
    void toXmlHelper(double);
    void toXmlHelper(std::string const&);
}

您知道m_tyId 的类型,没有理由使用运行时类型信息。警告显示为为类模板的所有实例编译的代码(在每个 if 类中),即使它没有意义,例如将浮点数分配给字符串。

【讨论】:

  • 是的,部分专业化...没有考虑到这一点。谢谢你的样品,我会试试的,它看起来不错。会让你知道它是否有效。到目前为止,非常感谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
相关资源
最近更新 更多