【问题标题】:Restricting template instantiation using is_integral / BOOST_STATIC_ASSERT使用 is_integral / BOOST_STATIC_ASSERT 限制模板实例化
【发布时间】:2010-09-28 09:47:55
【问题描述】:

我正在尝试实现一个免费的运算符函数,以便将任意数据类型的值流式传输到某个容器类 (DataVector)。
我为项目中使用的基本数据类型和复杂数据类型做了一个模板(示例仅涵盖 std::string)。
为了确保模板不会与基本实现未正确处理的数据类型一起使用,我想使用类型特征(is_integral)限制实例化。多次尝试将 is_enabled is_integral 嵌入到运算符的签名中都失败了,我最终得到了下面示例中所示的实现。

typedef std::vector<unsigned char> DataVector;

template<typename T>
DataVector& operator <<(DataVector& vecArchive, T dataToAppend)
{
    if (boost::is_integral<T>::value == true)
    {
        // ... do something
        return vecArchive;
    }
    BOOST_STATIC_ASSERT(false);
};

template<> inline
DataVector& operator << <string> (DataVector& vecArchive, string dataToAppend)
{
    // do something different
    return vecArchive;
};

问题是它无法编译,即使是整数数据类型。我猜 BOOST_STATIC_ASSERT 不能在条件表达式中使用。如何做呢?任何帮助将不胜感激。

main()
{
    DataVector vecTel;
    vecTel << (int)5;  // ok
    vecTel << std::string("Hello World");  // ok
    vecTel << std::map(int, int)  // must fail
}

编译器错误:

d:...\TcpSerializable.h(52) : 错误 C2027: 使用未定义类型 'boost::STATIC_ASSERTION_FAILURE' 和 [ x=假 ] .\Telegram050.cpp(38) : 请参阅正在编译的函数模板实例化 'BasisKlassen::DataVector &BasisKlassen::operator

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    我不是boost 方面的专家,但从外观上看,即使boost::is_integral&lt;T&gt;::value 返回true,BOOST_STATIC_ASSERT(0) 也会编译(类似于所有其他正常功能)。因此,您会收到编译器错误(当静态断言的条件返回 false 时,这是预期的)。要解决此问题,最简单的方法是将函数更改为:

    template<typename T>
    DataVector& operator <<(DataVector& vecArchive, T dataToAppend)
    {
        BOOST_STATIC_ASSERT(boost::is_integral<T>::value);
        // ... do something
        return vecArchive;
    
    };
    

    【讨论】:

      【解决方案2】:

      如果您确实需要将某个实现限制为整数类型,您可以使用 boost 的 enable_if

      #include <boost/type_traits.hpp>
      #include <boost/utility.hpp>
      
      // operator<< for integral types
      template<typename T>
      typename boost::enable_if< boost::is_integral<T>, DataVector& >::type
      operator<<(DataVector& vecArchive, T dataToAppend) {
          // ... do something
          return vecArchive;
      };
      
      // different operator<< for std::string
      DataVector& operator<<(DataVector &vecArchive, const std::string &dataToAppend) {
          return vecArchive;
      }
      

      如果您尝试将其与非整数类型一起使用,则会出现常见的编译器错误,即找不到匹配的 operator&lt;&lt;

      【讨论】:

      • 感谢您的回答。这是我之前尝试过的方式,但是像这样,专业化将不再编译。错误 C2912:显式特化; ...不是功能模板的特化
      • @raines:可能因为这个模板“只存在”于整数类型,所以没有什么可以专门用于其他类型。但是无论如何,使用简单的重载(就像我编辑到我的答案中一样)而不是那些其他类型的模板特化,你可能会更好。如果您只是为其他类型的 operator&lt;&lt; 创建新的重载函数/模板,则应该正确解析。 (更多详情请参见here
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多