从C++ 11到C++ 17,range-for循环等效于以下代码:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
Run Code Online (Sandbox Code Playgroud)
从C++ 17开始,等价将(显然)更新为这个:
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
Run Code Online (Sandbox Code Playgroud)
乍一看,我能看到的唯一区别在于,__begin
并且__end
不再共享类型,只要它们(让我说)可比较.
还有其他原因需要这种改变吗?
在过去的几个小时里,我一直在努力解决非常奇怪的问题(在我刚接触SFINAE并解决了5-6个其他问题之后)。基本上,在以下代码中,我希望可以f()
处理所有可能的模板实例化,但是g()
仅在N == 2
以下情况下可用:
#include <type_traits>
#include <iostream>
template<typename T, int N>
class A
{
public:
void f(void);
void g(void);
};
template<typename T, int N>
inline void A<T, N>::f()
{
std::cout << "f()\n";
}
template<typename T, int N, typename std::enable_if<N == 2, void>::type* = nullptr>
inline void A<T, N>::g()
{
std::cout << "g()\n";
}
int main(int argc, char *argv[])
{
A<float, 2> obj;
obj.f();
obj.g();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试对其进行编译时,我得到一个关于3个模板参数而不是2个模板参数的错误。然后,经过一番尝试,我决定将g()
内部的定义移到其A
自身的定义内,如下所示:
#include <type_traits> …
Run Code Online (Sandbox Code Playgroud) 我正在检查C++11功能并看到以下代码:
class conststr {
const char* p;
std::size_t sz;
public:
template<std::size_t N>
constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
};
Run Code Online (Sandbox Code Playgroud)
我知道const char a[]
,但我很困惑const char(&a)[N]
,有人知道如何使用它吗?
从 的文档来看configure_file
,它有一个有用的@ONLY
参数,用于:
将变量替换限制为表单的引用
@VAR@
。这对于配置使用${VAR}
语法的脚本很有用。
到现在为止还挺好。
现在我的情况是我有一个包含@FOO@
和的文件,${BAR}
我想S{BAR}
用一个来自我的CMakeLists.tx
. 另一方面,我不希望它configure_file
试图替换@FOO@
.
换句话说,我需要一个类似$ONLY
参数的东西,@ONLY
但它适用于相反的情况。
我现在有什么机会可以做到这一点吗?
我试图把反斜线在我的面前@
,但这样一来我得到一个包含几个文件\@
,这不正是我需要的。
最明显的答案可能是 - 因为标准是这样说的.
那很好,但是我正在绕着它去理解这个选择背后的原因.
请考虑以下示例:
template<typename T>
struct S { S(T) {} };
S f() { return 0; }
int main() {
auto s = f();
(void)s;
}
Run Code Online (Sandbox Code Playgroud)
它无法编译错误,如:
错误:使用类模板'S'需要模板参数; 函数返回类型中不允许使用参数推导
很容易修复,这不是问题,像这样的工作正常:
auto f() { return S{0}; }
Run Code Online (Sandbox Code Playgroud)
但是,我想了解在函数返回类型中允许类模板参数推导的缺点是什么.
乍一看,它看起来就像一个愚蠢的限制,但我很确定我在这里缺少一些重要的东西.
这是一个问题,其原因对我来说很模糊,但幸运的是,解决方法很容易。
考虑以下代码(让我称其为 my main.cpp
):
#include <algorithm>
struct Foo {
static constexpr float BAR = .42;
float operator()() const noexcept {
float zero = .0;
return std::min(zero, BAR);
}
};
int main() {
Foo foo;
foo();
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译它时,出现错误:
foobar:~/stackoverflow$ g++ -std=c++11 main.cpp
/tmp/ccjULTPy.o: 在函数 'Foo::operator()() const':
main.cpp:(.text._ZNK3FooclEv[_ZNK3FooclEv] +0x1a):对‘Foo::BAR’的未定义引用
collect2:错误:ld 返回 1 个退出状态
如果我使用以下语句,也会发生同样的情况(很明显):
return std::min(zero, Foo::BAR);
Run Code Online (Sandbox Code Playgroud)
下面是上面示例的稍微修改的版本。
这个编译没有错误,即使我仍然指的是BAR
成员:
#include <algorithm>
struct Foo {
static constexpr float BAR = .42;
float operator()() const noexcept {
float zero = .0; …
Run Code Online (Sandbox Code Playgroud) 我正在寻找一个标准的C++ 14类型模板,静态地(在编译时)嵌入一个函数引用作为模板参数,并实现operator()
作为对引用函数的转发调用.
我知道std::function
存在,但它将函数指针存储为数据成员.我希望将函数引用嵌入到类型签名中,以便包装器类型为空且默认可构造.
我有一个工作实现(使用示例用例):
#include <cstring>
#include <iostream>
#include <memory>
// Implementation:
template <typename Ret, typename... Args>
struct fn_t {
template <Ret (Func)(Args...)>
struct fn_ref {
Ret operator () (Args &&...args) const {
return Func(std::forward<Args>(args)...);
}
};
};
// Example use case:
template <typename T>
using unique_c_ptr = std::unique_ptr<T, fn_t<void, void *>::fn_ref<std::free>>;
int main() {
// { char *, void (*)(void *) } (16 bytes)
std::unique_ptr<char[], decltype(&std::free)> ptr1(::strdup("Hello"), &std::free);
// { char …
Run Code Online (Sandbox Code Playgroud) 如何在不使用的情况下将程序图标设置为警报alert.initOwner()
?为什么没有initOwner
?这是因为在初始化整个窗口之前必须显示一些警报,所以没有可以启用的场景initOwner
。
template<typename T> class SomeClass{
public:
enum SomeEnum{ SOME_FLAG};
};
SomeClass::SomeEnum some_enum = SomeClass::SomeEnum::SOME_FLAG; //NO
SomeClass<int>::SomeEnum some_enum = SomeClass::SomeEnum::SOME_FLAG; //NO
SomeClass<int>::SomeEnum some_enum = SomeClass<int>::SomeEnum::SOME_FLAG; //YES
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为
类SomeClass,不带模板参数
没有模版参数,没有办法/解决方法使用它,有点使该类的枚举成为全局类,因此它不依赖于该参数。
不是我不能输入它们,而是它们可能又长又复杂,代码将更难阅读,在这里我不能使用诸如auto之类的东西。(我是模板的新手,如果这个问题很me脚,抱歉。)
在处理现实项目时,我偶然发现了某些(某些版本)编译器的奇怪行为。考虑以下类声明:
struct OptionalsStruct {
struct InnerType {
bool b{};
};
OptionalsStruct() = default;
std::optional<InnerType> oInnerType;
};
Run Code Online (Sandbox Code Playgroud)
对于某些编译器,它OptionalStruct::InnerType
是不可构造的,但不可构造或默认可构造的(clang 11到16和GCC 10),对于其他一些编译器,它既不是不可构造的(clang 9和10),更不用说clang 8如何看待整体事物。
我的问题是:这些行为是编译器错误,还是标准中的漏洞(我使用的是 C++17)?我在这里错过了什么吗?