代码之家  ›  专栏  ›  技术社区  ›  sharptooth

当模板类不包含可用的成员函数时,如何在编译时验证模板参数?

  •  6
  • sharptooth  · 技术社区  · 15 年前

    我有一个模板 struct :

    template<int Degree>
    struct CPowerOfTen {
    enum { Value = 10 * CPowerOfTen<Degree - 1>::Value };
    };
    
    template<>
    struct CPowerOfTen<0> {
        enum { Value = 1 };
    };
    

    使用方法如下:

    const int NumberOfDecimalDigits = 5;
    const int MaxRepresentableValue = CPowerOfTen<NumberOfDecimalDigits>::Value - 1;
    // now can use both constants safely - they're surely in sync
    

    现在模板需要 Degree 不是消极的。我想强制执行一个编译时断言。

    我该怎么做?我试图添加一个析构函数到 CPowerOfTen

    ~CPowerOfTen() {
        compileTimeAssert( Degree >= 0 );
     }
    

    但是由于它没有被直接调用Visual C++ 9决定不实例化它,所以编译时断言语句根本不被评估。

    如何强制执行编译时检查 不是消极的?

    5 回复  |  直到 15 年前
        1
  •  8
  •   Alexey Malistov    15 年前
    template<bool> struct StaticCheck;
    template<> struct StaticCheck<true> {};
    
    template<int Degree> 
    struct CPowerOfTen : StaticCheck<(Degree > 0)> { 
        enum { Value = 10 * CPowerOfTen<Degree - 1>::Value }; 
    }; 
    
    template<> 
    struct CPowerOfTen<0> { 
        enum { Value = 1 }; 
    }; 
    

    编辑: 没有无限递归。

    // Help struct
    template<bool, int> struct CPowerOfTenHelp;
    
    // positive case    
    template<int Degree> 
    struct CPowerOfTenHelp<true, Degree> { 
        enum { Value = 10 * CPowerOfTenHelp<true, Degree - 1>::Value }; 
    }; 
    
    template<> 
    struct CPowerOfTenHelp<true, 0> { 
        enum { Value = 1 }; 
    }; 
    
    // negative case
    template<int Degree> 
    struct CPowerOfTenHelp<false, Degree> {}
    
    // Main struct
    template<int Degree> 
    struct CPowerOfTen : CPowerOfTenHelp<(Degree >= 0), Degree> {};
    
        2
  •  5
  •   DanDan    15 年前

    你可以用尿布。您不会得到编译时错误,但至少它是自文档的。

        3
  •  5
  •   David Rodríguez - dribeas    15 年前

    你可以用 BOOST_STATIC_ASSERT 宏。或者实现自己的方法,强制失败的最简单方法是执行N个元素数组的typedef,其中N是正/负的,具体取决于参数。

    这种方法的问题是它将产生一个失败,但仍将尝试执行递归。看一看 boost::enable_if_c

        4
  •  2
  •   visitor    15 年前

    您可以将实现转发到同时接受bool参数的类,该参数指示是否可以计算结果。

    #include <limits>
    template <int Degree, bool InRange>
    struct PowerOfTenImpl
    {
        enum {Value = 10 * PowerOfTenImpl<Degree - 1, InRange>::Value};
    };
    
    template <>
    struct PowerOfTenImpl<0, true>
    {
        enum {Value = 1};
    };
    
    template <int Degree>
    struct PowerOfTenImpl<Degree, false>
    {
    };
    
    template<int Degree>
    struct CPowerOfTen {
        enum { Value = PowerOfTenImpl<Degree, Degree >= 0 && 
          Degree <= std::numeric_limits<int>::digits10>::Value };
    };
    
    int main()
    {
        const int a = CPowerOfTen<4>::Value;
        const int b = CPowerOfTen<1000>::Value;
        const int c = CPowerOfTen<-4>::Value;
    }
    
        5
  •  1
  •   Prasoon Saurav    15 年前

    实施一个 STATIC_CHECK 宏?

    template<bool> struct CompileTimeError;
    template<> struct CompileTimeError<true> {}; //specialized only for true
    
    #define STATIC_CHECK(expr)  (CompileTimeError<(expr) != 0>())
    

    内部 main()

     const int NumberOfDecimalDigits = -1;
     STATIC_CHECK(NumberOfDecimalDigits > 0); // Error : invalid use of incomplete type struct CompileTimeError<false>
    
     const int MaxRepresentableValue = CPowerOfTen<NumberOfDecimalDigits>::Value - 1;