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
Post a Comment