标签: constexpr

{fmt}:始终在函数中编译时检查格式字符串

我正在尝试创建一个自定义错误类,其构造函数通过将参数传递给fmt::format(). 我希望它始终在编译时根据参数检查格式字符串,而不必FMT_STRING()每次抛出时都显式使用。就像是:

class Err : public std::exception 
{
private:
    std::string m_text;
public: 
    template <typename S, typename... Args>
    Err(const S& format, Args&&... args) {
        m_text = fmt::format(FMT_STRING(format), args...);
    }
    
    virtual const char* what() const noexcept {return m_text.c_str();}
};

// ------------------------ 

throw Err("Error {:d}", 10);     // works
throw Err("Error {:d}", "abc");  // cause Compile-time error
Run Code Online (Sandbox Code Playgroud)

使用前面的代码,我在 FMT_STRING() 宏上收到错误:

error C2326: 'Err::{ctor}::<lambda_1>::()::FMT_COMPILE_STRING::operator fmt::v7::basic_string_view<char>(void) const': function cannot access 'format' 
message : see reference to function template instantiation 'Err::Err<char[11],int>(const S (&),int …
Run Code Online (Sandbox Code Playgroud)

c++ compile-time constexpr fmt

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

在 constexpr 分支中使用枚举类值

下面的代码会val2在两次f()调用中打印。f()根据枚举值执行特定分支的正确方法是什么?

enum class E
{
    val1,
    val2
};

using val1_t = std::integral_constant<E, E::val1>;
using val2_t = std::integral_constant<E, E::val2>;
    

template <typename T>
void f(T t)
{
    if constexpr (std::is_same_v<T, val1_t>)
    {
        std::cerr << "val1\n";
    }
    else
    {
        std::cerr << "val2\n";
    }
}


int main()
{
    f(E::val1);
    f(E::val2);
}
Run Code Online (Sandbox Code Playgroud)

c++ enums constexpr c++17 tag-dispatching

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

如何使用 C++ 模块:带有模板的私有片段?

我正在尝试 C++20,以更好地了解它们在实践中的工作原理。我了解了module :private可用于将接口与实现分离的片段,同时将两者保留在同一个文件中。这似乎适用于标准函数,但不适用于模板函数。

我有以下文件:

// File "main.cpp"

#include <iostream>

import mymodule;

int main()
{
    std::cout << "greeting(): " << mymodule::greetings() << std::endl;
    int x = 1;
    int y = 2;
    std::cout << "add(x, y): " << mymodule::add(x, y) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
// File "mymodule.ixx"

module;

#include <string>

// declare interface
export module mymodule;

export namespace mymodule {
    template<typename T>
    T add(T x, T y);

    std::string greetings();
}

// implement interface
module :private;

std::string mymodule::greetings() {
    return "hello";
} …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++20 c++-modules

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

删除常量表达式中带符号整数溢出的未定义行为?

编辑在实际示例中,似乎可能会发生负溢出,我还添加了一个示例来演示那里的错误

我正在使用 C++20 并尝试将依赖于 Java 和 C# 中的有符号整数溢出的库转换为 C++ 代码。我还尝试生成它在编译时使用的表,并允许它们在编译时可用。

在我的代码中,我在引用看起来像这样的代码时遇到错误(重现错误的最小示例,该解决方案也将解决我的问题):

#include <iostream> 

constexpr auto foo(){
    std::int64_t a = 2; 
    std::int64_t very_large_constant = 0x598CD327003817B5L; 
    std::int64_t x = a * very_large_constant; 
    return x; 
}
 
int main(){
    std::cout << foo() << std::endl; 
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/TvM45vd8d

负溢出版本

#include <iostream> 

constexpr auto foo(){
    std::int64_t a = -2; 
    std::int64_t very_large_constant = 0x598CD327003817B5L; 
    std::int64_t x = a * very_large_constant; 
    return x; 
}
 
int main(){
    std::cout << foo() << std::endl; 
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/7zoE9r18E

我得到 12905529061151879018 …

c++ integer-overflow undefined-behavior constexpr c++20

2
推荐指数
2
解决办法
225
查看次数

如何检查 const 数组成员在编译时单调增长

假设我们有 const 数组:

const int g_Values[] = { ... };
Run Code Online (Sandbox Code Playgroud)

如何检查成员在编译时单调增长,即g_Values[i] < g_Values[i + 1]

在运行时可以这样检查:

bool IsMonotonously()
{
    int i = _countof(g_Values);
    int m = MAXINT;
    do 
    {
        int v = g_Values[--i];
        if (v >= m) return false;
        m = v;
    } while (i);
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但如何用 constexpr 重写它并 if IsMonotonously()return false- 生成编译时错误。

c++ constexpr constexpr-function

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

从 constexpr 字符串初始化字符数组

我有类似这样的代码:

#define STR "ABC"
// ...
char s[] = STR;
puts(s);
s[2] = '!';
puts(s);
Run Code Online (Sandbox Code Playgroud)

我尝试用 constexpr 对其进行现代化改造:

constexpr char STR[] = "ABC"
// ...
char s[] = STR;
puts(s);
s[2] = '!';
puts(s);
Run Code Online (Sandbox Code Playgroud)

但它不再编译。

如何从 constexpr 常量初始化堆栈上的字符串而不产生运行时损失?

c++ constexpr

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

尝试从 std::array 编译 .data() 作为 c++20 中的 constexpr 函数时出错

我试图在编译时计算一个数组以加速某些函数,但遇到一个错误,但无法在 cppreference 的帮助下解决该错误。

代码归结为:

#include <cstddef>
#include <array>

template<typename T, size_t size>
constexpr auto giveArray()
{
    std::array<T, size> arr;
    for(size_t i = 0; i < size; ++i)
        arr[i] = 0;
    return arr;
}

constexpr auto arr = giveArray<int,10>().data();
Run Code Online (Sandbox Code Playgroud)

在 ubuntu 上使用“$ g++ -std=c++20 code.cpp”进行编译时,出现错误:.data() 不是 constexpr 函数,但它确实是。为什么我会收到此错误以及如何修复它,同时仍在编译时运行此函数并仅存储指针,而不存储 std::array 对象?

c++ constexpr stdarray c++20 constexpr-function

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

如何定义一个 constexpr 构造数组,该数组在多个翻译单元上只有一个实例?

我正在生成constexpr std::array一个类的内部constexpr,但我只想在使用该类的所有项目中使用该类的一个实例。

我最初将其设为全局变量,但后来发现,如果我在多个翻译单元中迭代数组,这些全局变量就会重复。然后我尝试使用一个constexpr函数,但我无法拥有static这样一个函数的内部。我使用的是c++14,所以我不能使用变量inline constexpr。变量extern constexpr没有意义,因为如果将声明与定义分开,那么constexpr当只需要一项时,如何以编译时而不是运行时的方式处理这些值?

还有其他选择吗?

编辑:参见https://godbolt.org/z/5PcboYov4

请记住,我没有定义常规变量。我正在定义一个constexpr变量。区别很重要。它被用于非上下文constexprconstexpr上下文中。

c++ constexpr c++14

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

验证固定长度字符串数组在编译时是否已排序

当尝试验证固定长度字符串数组在编译时是否已排序时,使用 时会出现奇怪的行为strncmp

如果验证函数引用全局数组,则 N 的所有值似乎都有效。

#include <cstring>

#define N 8 // vary values of N

const char STRINGS[][N] = {"a", "b", "c"};

constexpr bool is_sorted_global() {
    for (int i = 0; i < sizeof(STRINGS) / N - 1; i++) {
        if (strncmp(STRINGS[i], STRINGS[i + 1], N) > 0) {
            return false;
        }
    }

    return true;
}

int main()
{
    // always works for any N
    static_assert(is_sorted_global(), "list is not sorted");
}
Run Code Online (Sandbox Code Playgroud)

但是,如果使用函数模板,则只有 N 小于或等于 8 的值才有效。

template<const char …
Run Code Online (Sandbox Code Playgroud)

c++ sorting c-strings static-assert constexpr

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

gcc:C23 中的 constexpr 函数?

在使用constexprGCC v14.0(应该接近即将发布的 GCC v13.1)时,我编译了以下模块:

constexpr int f (int x)
{
    return x + 2;
}

constexpr const int x[] = { f(1) };
Run Code Online (Sandbox Code Playgroud)

gcc -std=c2x -c foo.c -O2 GCC 会抛出:

foo.c:1:1: error: 'constexpr' requires an initialized data declaration
   1 | constexpr int f (int x)
     | ^~~~~~~~~
[...f'up errors due to the one above...]
Run Code Online (Sandbox Code Playgroud)

根据constexprC23 提案 (pdf),这应该是正确的语法。不过该 PDF 没有附带任何示例,那么我在这里缺少什么?

GCC 自 C++11 起就可以处理constexpr,因此在 C 前端实现它应该是已知且成熟的技术。

c gcc constexpr c23

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