当前位置: 首页 > 知识库问答 >
问题:

C 14中的简单constexpr查找表

耿敏达
2023-03-14

我正在尝试基于整数数组制作一个简单的LookUptable,其想法是在html" target="_blank">编译时计算它。

为了使它能够用于我将来可能拥有的任何其他各种整数类型的表,我需要它作为一个模板。

所以我有一个查找表

#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

我试图在一个类中使用它来快速衰减整数信号,以整数距离。

例如。这只是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视频教程:Scott Schurr“constexpr:Applications”和其他,但它不会编译并给出错误;

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

静态断言失败

error: non-constant condition for static assertion

表示它在编译时没有计算任何内容。

我对C语言不熟悉。

我知道我正在做一些显而易见的事情,但我不知道它是什么。

我是否滥用了静态或 constexpr?

numeric_limits是常客?

我做错了什么?谢谢。

共有1个答案

宋经赋
2023-03-14

一些观察

1)正如michalsrb所观察到的,当您初始化< code > m _ distance attenuation 并且< code>DistanceAttenuation是< code>Foo的一部分时,< code>Foo是不完整的。

不幸的是,您不能用不完整的类型初始化<code>静态constexpr</code>成员(jogojapan在这个答案中对此做了更好的解释)。

建议:在Foo之外(和之前)定义距离衰减;所以它是一个完整的类型,可以用来初始化m_distanceAttenuation;类似的东西

 template <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 中的测试永远为真

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

因为std::size_t总是

4) 在 attenuateFoo() 中,您使用变量定义为 m_distanceAttenuationm_DistanceAttenuation;建议:更正所用变量的 che 名称

5) 在 attenuateFoo() 中,使用 : 运算符调用方法attenuateSignalByDistance();建议:使用 . 运算符,所以(也考虑第 (4) 点)

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

 类似资料:
  • 问题内容: 这是我的第一篇文章,请保持温柔。 我最近开始在工作中使用Powershell来更改广告组,查找广告信息等。但是我缺少我非常喜欢Java的GUI。 有没有一种简单的方法(或代码示例),可用来输入目标主机名并返回要求的详细信息。广告memberhsip组,帐户信息等? 我对Java的了解不如对Powershell的了解,因此会尽可能多地提供帮助。 谢谢 问题答案: 如果您正在寻找完整的Ja

  • 问题内容: 问题是很自我解释。我想做一个简单的查找和替换,就像在文本编辑器中处理数据库列(MS Windows Server 2003上的MsSQL)中的数据一样 问题答案: 以下查询将每个字符替换为一个字符。 这在SQL Server 2003上不起作用。

  • 问题内容: 我目前在理解和编写递归查询时遇到一些麻烦。我知道递归查询用于搜索信息层次结构,但是我还没有找到一个可以遍历层次结构的简单在线解决方案。例如,假设我有一个对家谱建模的关系: 如果我想编写一个遍历此家谱的递归查询,收集所有父母直到出生,我该如何处理? 提前致谢。 问题答案: 您可以使用子句。 在您的情况下,SQL可能类似于:

  • 本文向大家介绍Java实现的两种常见简单查找算法示例【快速查找与二分查找】,包括了Java实现的两种常见简单查找算法示例【快速查找与二分查找】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java实现的两种常见简单查找算法。分享给大家供大家参考,具体如下: 前言: 查找是指从一批记录当中找出满足制定条件的某一记录的过程。 在平常的程序的编写当中很多时候时用得上的,这里简单介绍两个查找算法

  • 我刚开始使用Spring Boot,正在尝试使用JPA存储库。我试图找出spring SimpleJarepository类在运行时保存数据库表的位置,以执行进一步的检索操作。我有以下服务类检索用户基于用户名。在eclipse中,我尝试在第9行检查userRepository,但我不知道从哪里可以找到Spring从DB表提取的值。我知道类将包含我试图查找的详细信息,但我想看看这些详细信息在中的位置

  • 仅使用一个组合查找表(mySQL数据库)来存储表之间的“链接”比使用单独的查找表有大的缺点(可能在查询速度等方面)吗?我之所以这么问,是因为在我的项目场景中,我最终会得到超过100个单独的查找表,我认为设置和维护这些表将会有很多工作。但为了更简单地举例,这里是一个仅包含4个表的简化场景: 表:教师 表:学生 表:类 表:languageSpoken ========================