c++ - Simple constexpr LookUpTable in C++14 -


i trying make simple lookuptable based on array of integers, idea have calculated @ compile time.

trying make possible use other future tables of various integer types might have, need template.

so have 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 compile-time interpreter!      public:         // construct , populate lookuptable such that;         //   indices of values mapped data values stored         constexpr lookuptableindexed() : m_lut {}         {             //ctor         }          // returns number of values stored         constexpr std::size_t size() const {return number_of_elements;}          // returns data value @ 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 , end of lookuptable         constexpr iterator begin() {return &m_lut[0                 ];}         constexpr iterator end  () {return &m_lut[number_of_elements];} };  #endif // lookuptable_h 

and i'm trying use in class rapid attenuation of integer signal wrt integer distance.

eg. sample usage 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 can held in type         //constexpr auto maximum_distance = std::numeric_limits<tdistance>::max();          // number of bits used type         //constexpr auto number_of_digits = std::numeric_limits<tdistance>::digits;          // lookuptable         lookuptableindexed<tdistance, number_of_digits> m_attenuationrangeupperlimit {}; // essential lookuptable default constructor compile-time interpreter!          // returns number of bits bit-shift-right, attenuate, signal         // given distance source         constexpr std::size_t attenuateby(const tdistance distance)         {             (std::size_t {number_of_digits}; (i > 0); --i)             {                 // while distance exceeds upper-limit, keep trying values                 if (distance >= m_attenuationrangeupperlimit[i - 1])                 {                     // found range given distance occupies                     return (i - 1);                 }             }             throw std::logic_error("distanceattenuation::attenuateby(cannot attenuate signal using given distance!)");         }      public:         // calculate distance correction factors signals         // can attenuated emulate the effects of distance on signal strength         // ...using inverse square relationship of distance signal strength         constexpr distanceattenuation() : m_attenuationrangeupperlimit {}         {             //ctor              // populate lookuptable             (std::size_t {0}; (i < number_of_digits); ++i)             {                 tdistance goo = 0; // not attenuation calculation                 tdistance hoo = 0; // **for test only!**                 m_attenuationrangeupperlimit[i] = maximum_distance - goo - hoo;             }             static_assert((m_attenuationrangeupperlimit[0] == maximum_distance),                           "distanceattenuation : failed build lut!");        }          // attenuate signal, s, effect of distance          // factor, a, where;         // positive contribution values attenuated down toward 0         // negative                                             0         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() {}      // integer foo     signed int attenuatefoo(signed int signal, sdistance_t distance) {return m_distanceattenuation::attenuatesignalbydistance(signal, distance);}  };  #endif // foo_h 

i have tried several ways, using youtube video tutorial cppcon 2015: scott schurr “constexpr: applications" , others, won't compile giving error;

error: 'constexpr static auto m_distanceattenuation...' used before definition 

and static asserts fail with

error: non-constant condition static assertion 

indicating isn't calculating @ compile-time.

i'm new c++.

i know i'm doing obvious don't know is.

am misusing static or constexpr?

numeric_limits constexpr?

what doing wrong? thank you.

some observations

1) as observed michalsrb, foo isn't complete when initialize m_distanceattenuation , distanceattenuation part of foo, incomplete.

unfortunately can't initialize static constexpr member incomplete type (as better explained jogojapan in answer).

suggestion: define distanceattenuation outside (and before) foo; it's complete type , can used initialize m_distanceattenuation; like

 template <typename    tdistance,            tdistance   maximum_distance,            std::size_t number_of_digits>  struct distanceattenuation  {    // ...  };  class foo {   // ... }; 

2) in c++14, constexpr method isn't const method; suggestion: define following method const or can't use in constexpr expressions

constexpr std::size_t attenuateby (const tdistance distance) const constexpr signed int attenuatesignal(const signed int s, const int a) const constexpr signed int attenuatesignalbydistance(const signed int s, const tdistance d) const 

3) in attenuateby(), test in following for ever true

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

because std::size_t ever >= 0, for goes in loop , never exit; suggestion: redefine i int or long

4) in attenuatefoo() use m_distanceattenuation variable defined m_distanceattenuation; suggestion: correct che name of variable used

5) in attenuatefoo() call method attenuatesignalbydistance() using :: operator; suggestion: use . operator, (considering point (4) too)

signed int attenuatefoo(signed int signal, sdistance_t distance)  {return m_distanceattenuation.attenuatesignalbydistance(signal, distance);} 

Comments

Popular posts from this blog

java - Jasper subreport showing only one entry from the JSON data source when embedded in the Title band -

serialization - Convert Any type in scala to Array[Byte] and back -

SonarQube Plugin for Jenkins does not find SonarQube Scanner executable -