2016-09-07 88 views
8

我试图做一个简单的LookupTable中基于整数数组,这里的想法是有它在编译时计算上。简单constexpr LookupTable中C++ 14

试图使它可以用于我可能有的各种整数类型的任何其他未来表格,我可能需要它,我需要它作为模板

所以我有一个LookUpTable.h

#ifndef LOOKUPTABLE_H 
#define LOOKUPTABLE_H 

#include <stdexcept> // out_of_range 

template <typename T, std::size_t NUMBER_OF_ELEMENTS> 
class LookUpTableIndexed 
{ 
    private: 
     //constexpr static std::size_t NUMBER_OF_ELEMENTS = N; 

     // LookUpTable 
     T m_lut[ NUMBER_OF_ELEMENTS ] {}; // ESSENTIAL T Default Constructor for COMPILE-TIME INTERPRETER! 

    public: 
     // Construct and Populate the LookUpTable such that; 
     // INDICES of values are MAPPED to the DATA values stored 
     constexpr LookUpTableIndexed() : m_lut {} 
     { 
      //ctor 
     } 

     // Returns the number of values stored 
     constexpr std::size_t size() const {return NUMBER_OF_ELEMENTS;} 

     // Returns the DATA value at the given INDEX 
     constexpr T& operator[](std::size_t n) 
     { 
      if (n < NUMBER_OF_ELEMENTS) 
       return m_lut[n]; 
      else throw std::out_of_range("LookUpTableIndexed[] : OutOfRange!"); 
     } 
     constexpr const T& operator[](std::size_t n) const 
     { 
      if (n < NUMBER_OF_ELEMENTS) 
       return m_lut[n]; 
      else throw std::out_of_range("LookUpTableIndexed[] const : OutOfRange!"); 
     } 

     using iterator = T*; 

     // Returns beginning and end of LookUpTable 
     constexpr iterator begin() {return &m_lut[0     ];} 
     constexpr iterator end () {return &m_lut[NUMBER_OF_ELEMENTS];} 
}; 

#endif // LOOKUPTABLE_H 

而且我试图使用它在一个类的整数信号WRT的整数距离的快速衰减。

例如。这仅仅是一个样品用法foo.h中

#ifndef FOO_H 
#define FOO_H 

#include <limits> // max, digits 
#include <stdlib.h> // abs 

#include "LookUpTable.h" // LookUpTableIndexed 

class Foo 
{ 
private: 
    template <typename TDistance, 
       TDistance MAXIMUM_DISTANCE, 
       std::size_t NUMBER_OF_DIGITS> 
    struct DistanceAttenuation 
    { 
    private: 
     // Maximum value that can be held in this type 
     //constexpr auto MAXIMUM_DISTANCE = std::numeric_limits<TDistance>::max(); 

     // Number of bits used by this type 
     //constexpr auto NUMBER_OF_DIGITS = std::numeric_limits<TDistance>::digits; 

     // LookUpTable 
     LookUpTableIndexed<TDistance, NUMBER_OF_DIGITS> m_attenuationRangeUpperLimit {}; // ESSENTIAL LookUpTable Default Constructor for COMPILE-TIME INTERPRETER! 

     // Returns the number of bits to BIT-SHIFT-RIGHT, attenuate, some signal 
     // given its distance from source 
     constexpr std::size_t attenuateBy(const TDistance distance) 
     { 
      for (std::size_t i {NUMBER_OF_DIGITS}; (i > 0); --i) 
      { 
       // While distance exceeds upper-limit, keep trying values 
       if (distance >= m_attenuationRangeUpperLimit[i - 1]) 
       { 
        // Found RANGE the given distance occupies 
        return (i - 1); 
       } 
      } 
      throw std::logic_error("DistanceAttenuation::attenuateBy(Cannot attenuate signal using given distance!)"); 
     } 

    public: 
     // Calculate the distance correction factors for signals 
     // so they can be attenuated to emulate the the effects of distance on signal strength 
     // ...USING THE INVERSE SQUARE RELATIONSHIP OF DISTANCE TO SIGNAL STRENGTH 
     constexpr DistanceAttenuation() : m_attenuationRangeUpperLimit {} 
     { 
      //ctor 

      // Populate the LookUpTable 
      for (std::size_t i {0}; (i < NUMBER_OF_DIGITS); ++i) 
      { 
       TDistance goo = 0; // Not an attenuation calculation 
       TDistance hoo = 0; // **FOR TEST ONLY!** 
       m_attenuationRangeUpperLimit[i] = MAXIMUM_DISTANCE - goo - hoo; 
      } 
      static_assert((m_attenuationRangeUpperLimit[0] == MAXIMUM_DISTANCE), 
          "DistanceAttenuation : Failed to Build LUT!"); 
     } 

     // Attenuate the signal, s, by the effect of the distance 
     // by some factor, a, where; 
     // Positive contribution values are attenuated DOWN toward ZERO 
     // Negative         UP   ZERO 
     constexpr signed int attenuateSignal(const signed int s, const int a) 
     { 
      return (s < 0)? -(abs(s) >> a) : 
          (abs(s) >> a); 
     } 
     constexpr signed int attenuateSignalByDistance(const signed int s, const TDistance d) 
     { 
      return attenuateSignal(s, attenuateBy(d)); 
     } 

    }; 

    using SDistance_t = unsigned int; 

    constexpr static auto m_distanceAttenuation = DistanceAttenuation<SDistance_t, 
                     std::numeric_limits<SDistance_t>::max(), 
                     std::numeric_limits<SDistance_t>::digits>(); 

public: 
    Foo() {} 
    ~Foo() {} 

    // Do some integer foo 
    signed int attenuateFoo(signed int signal, SDistance_t distance) {return m_distanceAttenuation::attenuateSignalByDistance(signal, distance);} 

}; 

#endif // FOO_H 

我试图通过CppCon 2015年这样做有几个方法,使用YouTube视频教程:斯科特·舒尔“constexpr:应用”等人,但它不会给编译错误;

error: 'constexpr static auto m_distanceAttenuation...' used before its definition 

和静态断言失败,

error: non-constant condition for static assertion 

表示它不计算任何东西编译时间

我是C++新手。

我知道我在做一些明显的事情,但我不知道它是什么。

我是否滥用static or constexpr

numeric_limits是否是constexpr?

我在做什么错? 谢谢。

+1

对于一个你缺少收盘'>''为= DistanceAttenuation <...'。这是一个复制错误?除此之外,我非常怀疑,你可以在'DistanceAttenuation'的构造函数中做你想做的事情,但是我还没有使用C++ 14的constexpr。 – MikeMB

+0

您是否尝试了解非常明确的编译器错误消息建议您应该执行的操作?你知道“定义之前使用”是什么意思吗? –

+1

不知道正确的答案,但:1)“在定义之前使用”似乎是由使用嵌套类引起的。如果您将DistanceAttenuation移出Foo,它将起作用。 2)如果需要,constexpr构造函数必须是可编译的,以便在运行时运行,在这种情况下,'static_assert'内的表达式不会被constexpr。 – michalsrb

回答

0

一些观察

1)as observed by michalsrbFoo在初始化m_distanceAttenuationDistanceAttenuationFoo部分未完成,因此是不完整的。

可惜你不能初始化一个不完整的类型static constexpr成员(由jogojapan in this answer更好地解释)。

建议:限定DistanceAttenuation它外面(及前)Foo;所以它是一个完整的类型,可以用来初始化m_distanceAttenuation;在C++ 14类似

template <typename TDistance, 
      TDistance MAXIMUM_DISTANCE, 
      std::size_t NUMBER_OF_DIGITS> 
struct DistanceAttenuation 
{ 
    // ... 
}; 

class Foo 
{ 
    // ... 
}; 

2),constexpr方法不是const方法;建议:定义下面的方法const过,或者你不能在attenuateBy()使用他们在一些constexpr表达

3),在下面的for试验是有史以来真

for (std::size_t i {NUMBER_OF_DIGITS - 1}; (i >= 0); --i) 

因为std::size_t永远是>= 0,所以for进入循环,永远不会退出;建议:重新定义iintattenuateFoo()long

4)使用m_DistanceAttenuation其中变量被定义为m_distanceAttenuation;建议:变量的正确澈名attenuateFoo()使用

5)您使用::操作者调用方法attenuateSignalByDistance();建议:使用.操作,所以(考虑点(4)太)

signed int attenuateFoo(signed int signal, SDistance_t distance) 
{return m_distanceAttenuation.attenuateSignalByDistance(signal, distance);} 
+0

我不知道这是什么意思** 1)观察michalsrb,DistanceAttenuation没有在Foo中定义,如果您在Foo **中定义它... –

+0

我没有意识到* constexpr *没有工作一种隐含的* const *。我认为它只是一种* const ++ * –

+0

@DavidHParry - 你不确定我的意思是“DistanceAttenuation未在Foo中定义,如果你在Foo中定义它[...]”,因为我写了一个愚蠢的东西;抱歉。更正的答案(我希望)。 – max66