我正在尝试创建一个自定义错误类,其构造函数通过将参数传递给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) 下面的代码会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++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++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 …
假设我们有 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- 生成编译时错误。
我有类似这样的代码:
#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 常量初始化堆栈上的字符串而不产生运行时损失?
我试图在编译时计算一个数组以加速某些函数,但遇到一个错误,但无法在 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 对象?
我正在生成constexpr std::array一个类的内部constexpr,但我只想在使用该类的所有项目中使用该类的一个实例。
我最初将其设为全局变量,但后来发现,如果我在多个翻译单元中迭代数组,这些全局变量就会重复。然后我尝试使用一个constexpr函数,但我无法拥有static这样一个函数的内部。我使用的是c++14,所以我不能使用变量inline constexpr。变量extern constexpr没有意义,因为如果将声明与定义分开,那么constexpr当只需要一项时,如何以编译时而不是运行时的方式处理这些值?
还有其他选择吗?
编辑:参见https://godbolt.org/z/5PcboYov4
请记住,我没有定义常规变量。我正在定义一个constexpr变量。区别很重要。它被用于非上下文constexpr和constexpr上下文中。
当尝试验证固定长度字符串数组在编译时是否已排序时,使用 时会出现奇怪的行为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) 在使用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 前端实现它应该是已知且成熟的技术。