在C ++ 14简单constexpr LookUpTable [英] Simple constexpr LookUpTable in C++14
问题描述
我想根据整数数组制作一个简单 LookUpTable ,其中的想法是在编译时计算 。
尝试使用它可能用于任何其他未来的各种整数类型的表格,我可能需要它作为一个模板 。
所以我有一个 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 COMPILE-TIME INTERPRETER的默认构造函数!
public:
//构造和填充LookUpTable,
//值的INDICES映射到存储的DATA值
constexpr LookUpTableIndexed():m_lut {}
{
// ctor
}
//返回存储的值的数量
constexpr std :: size_t size()const {return NUMBER_OF_ELEMENTS;}
//返回给定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!);
}
使用iterator = T *;
//返回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
#includeLookUpTable.h// LookUpTableIndexed
class Foo
{
private:
template< typename TDistance,
TDistance MAXIMUM_DISTANCE,
std :: size_t NUMBER_OF_DIGITS>
struct DistanceAttenuation
{
private:
//可以在此类型中保存的最大值
// constexpr auto MAXIMUM_DISTANCE = std :: numeric_limits< TDistance> ;: :max();
//此类型使用的位数
// constexpr auto NUMBER_OF_DIGITS = std :: numeric_limits< TDistance> :: digits;
// LookUpTable
LookUpTableIndexed< TDistance,NUMBER_OF_DIGITS> m_attenuationRangeUpperLimit {}; // ESSENTIAL LookUpTable COMPILE-TIME INTERPRETER的默认构造函数!
//返回到BIT-SHIFT-RIGHT的位数,衰减一些信号
//给定它与源的距离
constexpr std :: size_t attenuateBy(const TDistance距离)
{
for(std :: size_t i {NUMBER_OF_DIGITS};(i> 0); --i)
{
//当距离超过上限,保持尝试值
if(distance> = m_attenuationRangeUpperLimit [i-1])$ b $ b {
//找到RANGE给定距离占用
return
}
}
throw std :: logic_error(DistanceAttenuation :: attenuateBy(Can not attenuate signal using given distance!));
}
public:
//计算信号的距离校正因子
//因此它们可以被衰减以模拟距离对信号强度的影响
// ...使用距离的反向平方关系到信号强度
constexpr DistanceAttenuation():m_attenuationRangeUpperLimit {}
{
// ctor
//填充LookUpTable
for(std :: size_t i {0};(i {
TDistance goo = 0; //不是衰减计算
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!
}
//通过距离
//的效果衰减信号s,通过某个因子a,其中;
//正向贡献值向ZERO向下衰减
//负向上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));
}
};
使用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(){}
//做一些整数foo
signed int attenuateFoo (signed int signal,SDistance_t distance){return m_distanceAttenuation :: attenuateSignalByDistance(signal,distance);}
};
#endif // FOO_H
我尝试过几种方法,使用 CppCon 2015:Scott Schurrconstexpr:Applications和其他人的YouTube视频教程,但不会编译出错误;
错误:'constexpr static auto m_distanceAttenuation ...'在其定义之前使用
且静态断言失败
错误:静态断言的非常量条件
运算符使用$ c> attenuateSignalByDistance()建议:使用
code>和
表示在编译时未计算任何内容。
我是C ++的新手。
我知道我在做一些明显的事,但我不知道是什么。
我是在使用 static 或 constexpr 吗?
> numeric_limits are constexpr?
我做错了什么?
谢谢。解决方案一些意见
DistanceAttenuation
是Foo
的一部分,因此不完整。
不幸的是,你不能初始化一个不完整类型的
static constexpr
成员(更好地解释由jogojapan 在此回答)。
建议:定义
DistanceAttenuation
它之外(和之前)Foo
所以它是一个完整的类型,可以用于初始化m_distanceAttenuation
;像模板< typename TDistance,
TDistance MAXIMUM_DISTANCE,
std :: size_t NUMBER_OF_DIGITS&
struct DistanceAttenuation
{
// ...
};
class Foo
{
// ...
};
2)在C ++ 14中,
constexpr
方法不是const
方法;建议:在const
中定义以下方法,或者您不能在一些constexpr
表达式中使用它们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 )在
attenuateBy()
中,在中测试是真的
for(std :: size_t i {NUMBER_OF_DIGITS - 1};(i> = 0); --i)
因为
std :: size_t
是> = 0
,因此for
进入循环,从不退出;建议:重新定义i
为int
或long
4)在
attenuateFoo()
中使用m_DistanceAttenuation
定义为m_distanceAttenuation
;建议:在attenuateFoo()
中调用变量的正确名称
< $ c> ::。
运算符,因此(也考虑点(4))signed int attenuateFoo(signed int signal,SDistance_t distance)
{return m_distanceAttenuation.attenuateSignalByDistance(signal,distance);}
I am trying to make a simple LookUpTable based on an array of integers, where the idea is to have it calculated at compile time.
Trying to make it possible to use it for any other future tables of various integer types I might have, I need it as a template.
So I have a 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
And I'm trying to use it in a class for rapid attenuation of an integer signal wrt an integer distance.
eg. This is just a sample usage as 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
I have tried to do this several ways, using the youtube video tutorial by CppCon 2015: Scott Schurr "constexpr: Applications" and others, but it won't compile giving the error;
error: 'constexpr static auto m_distanceAttenuation...' used before its definition
and the static asserts fail with
error: non-constant condition for static assertion
indicating it isn't calculating anything at compile-time.
I'm new to C++.
I know I'm doing something obvious but I don't know what it is.
Am I misusing static or constexpr?
numeric_limits are constexpr?
What am I doing wrong? Thank you.
解决方案Some observations
1) as observed by michalsrb,
Foo
isn't complete when you initializem_distanceAttenuation
andDistanceAttenuation
is part ofFoo
, so is incomplete.Unfortunately you can't initialize a
static constexpr
member with an incomplete type (as better explained by jogojapan in this answer).Suggestion: define
DistanceAttenuation
it outside (and before)Foo
; so it's a complete type and can be used to initializem_distanceAttenuation
; something liketemplate <typename TDistance, TDistance MAXIMUM_DISTANCE, std::size_t NUMBER_OF_DIGITS> struct DistanceAttenuation { // ... }; class Foo { // ... };
2) in C++14, a
constexpr
method isn't aconst
method; suggestion: define the following method asconst
too or you can't use they in someconstexpr
expressionsconstexpr 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()
, the test in the followingfor
is ever truefor (std::size_t i {NUMBER_OF_DIGITS - 1}; (i >= 0); --i)
because a
std::size_t
is ever>= 0
, so thefor
goes in loop and never exit; suggestion: redefinei
asint
orlong
4) in
attenuateFoo()
you usem_DistanceAttenuation
where the variable is defined asm_distanceAttenuation
; suggestion: correct che name of the variable used5) in
attenuateFoo()
you call the methodattenuateSignalByDistance()
using the::
operator; suggestion: use the.
operator, so (considering point (4) too)signed int attenuateFoo(signed int signal, SDistance_t distance) {return m_distanceAttenuation.attenuateSignalByDistance(signal, distance);}
这篇关于在C ++ 14简单constexpr LookUpTable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!