标签: constexpr

constexpr:constexpr 成员的定义和声明

如果我想使用一些方便的东西,比如make_array我没有机会先声明我的数组,然后再像“早期”那样进行定义,因为我的 var 的类型在定义之前不可用。

所以我找到了这个答案:
对 static constexpr char[] 的未定义引用

在下面的示例中,我编写了这个解决方案,它可以用 gcc 很好地编译,我不确定这是否是真正有效的 C++ 代码,因为它或多或少是一个带有定义的声明,后来是一个没有任何内容的定义。这是允许的吗?(编译良好并不能保证代码是有效的 C++ )

#include <experimental/array>
#include <iostream>

class Foo
{
    private:
    static decltype(auto) constexpr Bar =
        std::experimental::make_array(
            std::experimental::make_array( 1,2,3 ),
            std::experimental::make_array( 4,5,6 )
            );

    public:
    using ARR_TYPE = decltype( Bar );

    static auto& GetArr( int idx )
    {
        // range check ...
        return Bar[idx];
    }
};

constexpr Foo::ARR_TYPE Foo::Bar;

int main()
{
    for ( auto el: Foo::GetArr(0))
    {
        std::cout << el << std::endl;
    }
 }
Run Code Online (Sandbox Code Playgroud)

c++ static language-lawyer constexpr

1
推荐指数
1
解决办法
1453
查看次数

为什么constexpr是该类型的一部分?

为什么constexpr部分线?我觉得它就像内联一样.什么是真正的类型fg

这有效:

void f()
{
  auto f = []() { return 42; };
  auto p = f;

  static_assert(std::is_same_v<decltype(f), decltype(p)>);
}
Run Code Online (Sandbox Code Playgroud)

但这不是:

void g()
{
  constexpr auto f = []() { return 42; };
  auto p = f;

  static_assert(std::is_same_v<decltype(f), decltype(p)>);
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/g/Di4SJ5

c++ const constexpr c++11

1
推荐指数
1
解决办法
91
查看次数

在编译时读取文件(constexpr或其他)

C ++ 17是否提供任何在编译时加载/读取文件的方式?更具体地说,我想将文件的内容加载到const char*std::string_view等等。例如:

    constexpr const char* read_file_content(const char* file_path) {
        /* should read in the content of the file and return it */
        return "";
    }

    constexpr const char* file_path    = "some/folder/file.json";
    constexpr const char* file_content = read_file_content(file_path);
Run Code Online (Sandbox Code Playgroud)


我遇到过这个答案是否可以在编译时读取文件?从2014年开始。teivaz的解决方案使用一些宏和#include魔术完美地工作了。但是,它需要更改输入文件:该文件应将其内容包含在STR(...)中,但这可能并不总是可能的。

由于上述答案很旧,我认为可能情况已经改变,也许C ++ 17(或可能的C ++ 20)提供了一些功能来克服此问题。

c++ file-io constexpr c++17

1
推荐指数
1
解决办法
165
查看次数

C++17:在 .cpp 文件中定义静态 constexpr 成员函数

我在 .h 文件中声明了一个静态 constexpr 成员函数。如果我立即在头文件中定义该函数,则一切正常。我一般倾向于在 .cpp 文件中定义函数(即使我希望它们内联,我也会使用 inline 关键字并再次这样做)所以当我尝试这样做时,起初似乎没问题,但是当我尝试时要调用此函数,我收到以下错误:

static constexpr uint16_t ClassA::myFoo()' used before its definition

我想了解是否有办法在 .cpp 文件而不是头文件中定义静态 constexpr 成员函数。如果那不可能或可能由于我使用的编译器而受到限制,那么在 .h 文件中定义函数是否有任何副作用?(我知道它对于普通函数是显式内联的,但我不确定 constexper 静态函数)。

PS:我在一个小型嵌入式项目中使用 arm-none-eabi-g++ (c++17) 和 Clion。

c++ constexpr c++17

1
推荐指数
1
解决办法
265
查看次数

隐藏 constexpr 计算的最佳方法

我想创建一个 constexpr param 结构。它的几个成员将由 constexpr 函数计算。喜欢:

class Params {
public:
    static constexpr size_t featureWinW{ 7 };
    static constexpr size_t featureWinH{ 7 };

private:
    static constexpr size_t getKernelSize()
    {
        //complex calculation
        return 20;
    }

public:
    static constexpr size_t kernelSize{ getKernelSize() };
}
Run Code Online (Sandbox Code Playgroud)

我知道 getKernelSize 就像是在类外部定义的,所以代码是错误的:

error: ‘static constexpr size_t Params::getKernelSize()’ called in a constant expression before its definition is complete
Run Code Online (Sandbox Code Playgroud)

我应该如何重新格式化我的代码以使其有效,即使是具有类似私有计算函数的专用命名空间也不会产生垃圾邮件?

c++ constexpr c++14 c++17

1
推荐指数
1
解决办法
168
查看次数

如何从预处理器#if 指令调用 constexpr 函数?

我想将宏定义为字符串,稍后在编译时包含基于字符串比较的代码:

#include <iostream>
#include <string_view>

constexpr bool strings_equal(char const * a, char const * b) {
    return std::string_view(a)==b;
}

#define FOO "bar"


int main() {
#if strings_equal( FOO, "bar") == 0
    std::cout << "got a bar!" << '\n';
#endif
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译这个

$ g++ -std=c++17 test.cpp -o my_test
Run Code Online (Sandbox Code Playgroud)

给出错误:

test.cpp:12:18: error: missing binary operator before token "("
   12 | #if strings_equal( FOO, "bar") == 0
      |                  ^
Run Code Online (Sandbox Code Playgroud)

编辑

看来#if指令是否在函数内部很重要,因为如果它在函数内部,我们可以用它替换它if constexpr (...) { ... }但是如果它在 …

c++ constexpr string-view c++17

1
推荐指数
1
解决办法
189
查看次数

检查某种类型是否是模板类 std::optional 的实例

这些是模板 constexpr bool 来检查某个类型是否实例化 std::optional

template<typename>   constexpr bool is_optional = false;
template<typename T> constexpr bool is_optional<std::optional<T>> = true;
template<typename T> constexpr bool is_optional<std::optional<T>&> = true;  // avoid this
static_assert(not is_optional<int>);
static_assert(is_optional<std::optional<int>>);
static_assert(is_optional<std::optional<int>&>);
Run Code Online (Sandbox Code Playgroud)

为了详尽无遗,我需要添加

template<typename T> constexpr bool is_optional<std::optional<T>const&> = true;  // avoid this
template<typename T> constexpr bool is_optional<std::optional<T>&&> = true;  // avoid this
template<typename T> constexpr bool is_optional<std::optional<T>const> = true;  // avoid this
Run Code Online (Sandbox Code Playgroud)

和可能的挥发物。看起来太麻烦了。

有没有办法只为真实情况声明一个变量?

c++ templates constexpr

1
推荐指数
1
解决办法
74
查看次数

constexpr initializer_list 引发错误:“表达式必须具有常量值——引用或指向具有有限生命周期的临时指针”

这是问题所在:

int main() 
{
    constexpr std::initializer_list<int> my_ints {1, 2, 3};
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用 g++ (x86_64-posix-seh-rev0, version 8.1.0) 编译上述内容。但是 VS Code 引发了以下警告:

“表达式必须有一个常量值——生命周期有限的临时引用或指针”

当我删除说明constexpr符时,也就是当我将代码修改为

int main() 
{
    std::initializer_list<int> my_ints {1, 2, 3};
}
Run Code Online (Sandbox Code Playgroud)

错误消失了,所以声明 a 似乎有问题constexpr initializer_list

然而根据这个参考(https://en.cppreference.com/w/cpp/utility/initializer_list/initializer_list),声明一个constexpr initializer_list.

有人可以更深入地了解其工作原理constexprinitializer_list解释为什么会发生这种情况吗?

c++ intellisense initializer-list constexpr visual-studio-code

1
推荐指数
1
解决办法
136
查看次数

constexpr,或者不是 constexpr,这是个问题

constexpr在 C++中玩弄并注意到我希望理解的奇怪行为。考虑来自标准 5.19 部分的这段代码。

constexpr int f1(int k) {
    constexpr int x = k; // error: x is not initialized by a
                         // constant expression because lifetime of k
                         // began outside the initializer of x
    return x;
}
Run Code Online (Sandbox Code Playgroud)

作为错误状态,生命周期k在 的初始值设定项之外开始x,因此我们不能确定这x 将是一个常量表达式。

这里是相同功能的另一个版本。

constexpr int f1(int k) {
    return k;
}
Run Code Online (Sandbox Code Playgroud)

这个很好用,很好用。所以问题是,为什么这里的生命周期也k开始于返回值的初始值设定项之外,或者不是,或者这是因为 RVO 并且从技术上讲,如果只是遵循标准,这也应该是一个错误?

还有另一个问题,这个问题实际上是从这个问题产生的。我正在尝试编写constexprIPv4 类。为此,我使用了带有std::string_view. 所以我能够在编译时使用 gcc 10.3 和 -std=c++20

constexpr IPv4 myIP{"192.168.0.0"};
constexpr size_t …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20

1
推荐指数
1
解决办法
86
查看次数

循环语句的 std::is_same

我有两个结构,其方法在它们拥有的对象集合的开始和结束时返回迭代器。方法有不同的名称(这似乎是一个糟糕的应用程序架构,但这只是一个简化的模型):

struct A {
  std::vector<int>::iterator a_begin() { return v.begin(); }
  std::vector<int>::iterator a_end() { return v.end(); }

  std::vector<int> v = { 1, 2 };
};

struct B {
  std::vector<float>::iterator b_begin() { return v.begin(); }
  std::vector<float>::iterator b_end() { return v.end(); }

  std::vector<float> v = { 1.0f, 2.0f };
};
Run Code Online (Sandbox Code Playgroud)

我想编写一个模板函数,它将迭代给定的对象(类型 A 或类型 B)并对其元素做一些工作。我的做法是:

template<class T>
void foo(T t) {
  if constexpr (std::is_same_v<T, A>) {
    for (auto it = t.a_begin(); it != t.a_end(); it++) {
      // a lot of stuff
    }
  } else …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr

1
推荐指数
1
解决办法
73
查看次数