如果我想使用一些方便的东西,比如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) 为什么constexpr部分线?我觉得它就像内联一样.什么是真正的类型f的g?
这有效:
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)
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)提供了一些功能来克服此问题。
我在 .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。
我想创建一个 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)
我应该如何重新格式化我的代码以使其有效,即使是具有类似私有计算函数的专用命名空间也不会产生垃圾邮件?
我想将宏定义为字符串,稍后在编译时包含基于字符串比较的代码:
#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 (...) { ... }但是如果它在 …
这些是模板 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)
和可能的挥发物。看起来太麻烦了。
有没有办法只为真实情况声明一个变量?
这是问题所在:
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.
有人可以更深入地了解其工作原理constexpr并initializer_list解释为什么会发生这种情况吗?
c++ intellisense initializer-list constexpr visual-studio-code
我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) 我有两个结构,其方法在它们拥有的对象集合的开始和结束时返回迭代器。方法有不同的名称(这似乎是一个糟糕的应用程序架构,但这只是一个简化的模型):
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)