让我们考虑一个函数(它的可能实现之一),它将无符号短值(或任何其他无符号整数类型)的右N位置零.可能的实现可能如下所示:
template<unsigned int shift>
unsigned short zero_right(unsigned short arg) {
using type = unsigned short;
constexpr type mask = ~(type(0));
constexpr type right_zeros = mask << shift; // <-- error here
return arg & right_zeros;
}
int check() {
return zero_right<4>(16);
}
Run Code Online (Sandbox Code Playgroud)
使用此代码,我可以访问的所有编译器以某种方式抱怨可能的溢出.CLang是最明确的一个,有以下明确的信息:
错误:从'int'到'const type'的隐式转换(又名'const unsigned short')将值从1048560更改为65520 [-Werror,-Wconstant-conversion]
这个代码看起来很清晰,对我来说很明显,但是当3个编译器抱怨时,我变得非常紧张.我在这里错过了什么吗?真的有可能发生腥病吗?
PS虽然zeriong out左边X位的替代实现可能是受欢迎和有趣的,但这个问题的主要焦点是发布的代码的有效性.
根据cppreference部分核心常量表达式指出19)两个指针之间的减法运算符不是合法的常量表达式,直到c ++ 14.我可以假设以下代码是合法的c ++ 17代码或者这种解释是滥用吗?
int X, Y;
template <long long V>
struct S { };
int main() {
S<&X - &Y> s;
(void)s;
}
Run Code Online (Sandbox Code Playgroud) (扰流器 -这是一个自我回答的问题)让我们假设我有两个索引序列,例如using i1 = std::index_sequence<1, 3, 5, 7>;和using i2 = std::index_sequence<2, 4, 6, 8>;
我想创建一个数组(在编译时),该数组中将依次包含8个元素:1, 2, 3, 4, 5, 6, 7, 8,以便以下代码可以工作(例如,在全局范围内):
std::array<int, 8> arr = make_array(i1{}, i2{});
Run Code Online (Sandbox Code Playgroud)
注意:如果我只想要一个序列,则解决方案很简单:
template<size_t... Ix>
constexpr auto make_arr(std::index_sequence<Ix...> )
return std::array{Ix...};
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我需要连接两个序列,那并不是那么简单,例如,这是行不通的:
template<size_t... Ix1, size_t... Ix2>
constexpr auto make_arr(std::index_sequence<Ix1...>, std::index_sequence<Ix2...>)
return std::array{(Ix1, Ix2)...};
}
Run Code Online (Sandbox Code Playgroud)
(上面的代码将使用第二个序列中的值填充数组)。
另一个可能的解决方案是使用constexpr函数,该函数首先定义一个具有默认值的数组,然后将索引序列中的值复制到该数组中,但是虽然该方法适用于ints,但不适用于某些更为复杂的类型,这些类型不是默认的-可构造的(显然,它们不是索引序列的一部分,但可以是其他东西)。
是否有不需要循环和默认构造值的解决方案?任何可用的C ++标准都是公平的游戏。
c++ template-meta-programming variadic-templates constexpr c++17
C++标准,据我所知,C++也依赖于这些问题,它具有以下部分:
当整数类型的值转换为实际浮动类型时,如果正在转换的值可以在新类型中准确表示,则它将保持不变.如果转换的值在可以表示但不能精确表示的值的范围内,则结果是以实现定义的方式选择的最接近的较高或最接近的较低可表示值.如果要转换的值超出可以表示的值范围,则行为未定义.
有什么方法可以检查最后一个案例吗?在我看来,这最后一个未定义的行为是不可避免的.如果我有一个整数值,i并天真地检查类似的东西
i <= FLT_MAX
Run Code Online (Sandbox Code Playgroud)
我将(除了与精度相关的其他问题)已经触发它,因为比较首先转换i为a float(在这种情况下或通常为任何其他浮动类型),因此如果它超出范围,我们将得到未定义的行为.
或者是否有一些关于积分和浮动类型的相对大小的保证,这意味着"浮点数总是代表int的所有值(当然不一定完全正确)",或者至少"long double可以始终包含所有内容",这样我们就可以了可以做那种类型的比较?但是我找不到那样的东西.
这主要是一个理论练习,所以我对"在大多数架构中这些转换始终有效"的答案不感兴趣.让我们试着找到一种方法来检测这种溢出而不假设超出C(++)标准!:)
我想知道是否有任何O(n ^ 2)复杂度算法用于生成数组的所有子序列.我知道一个算法,但它需要O((2 ^ n)*n)时间.
int main() {
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; ++i)
cin >> a[i];
int64_t opsize = pow(2,n);
for (int counter = 1; counter < opsize; counter++) {
for (int j = 0; j < n; j++) {
if (counter & (1 << j))
cout << a[j] << " ";
}
cout << endl;
}
}
Run Code Online (Sandbox Code Playgroud) 我有以下示例(避免调用移动构造函数的扩展)
#include <cstdint>
class Interface
{
public:
Interface() = default;
virtual ~Interface() = default;
Interface(const Interface&) = delete;
Interface(Interface&&) = delete;
const Interface& operator=(const Interface&) = delete;
Interface& operator=(Interface&&) = delete;
};
class FooC : public Interface
{
public:
FooC(uint16_t iPort, uint16_t iPin)
: PORT(iPort)
, PIN(iPin)
{
};
FooC() = delete;
~FooC() override = default;
FooC(const FooC&) = delete;
FooC(FooC&&) = delete;
const FooC& operator=(const FooC&) = delete;
FooC& operator=(FooC&&) = delete;
private:
const uint16_t PORT;
const …Run Code Online (Sandbox Code Playgroud) 下面的代码编译并在clang上工作,但失败并出现"错误:在gcc上无效使用非静态数据成员'Outer :: a'":
#include <functional>
#include <vector>
#include <assert.h>
#include <iostream>
#include <memory>
class Outer
{
public:
bool a = false;
virtual void f() = 0;
template <typename T>
class Inner : public T
{
public:
virtual void f() override
{
a = true; // Note: accessed through inheritance, not through outer scope
}
};
};
struct Foo : Outer { };
int main()
{
Outer::Inner<Foo> f;
f.f();
}
Run Code Online (Sandbox Code Playgroud)
在内部类中添加"this-> a"使其适用于两个编译器,但我想知道正确的行为是什么以及标准对此有何看法.
有趣的是,上面的代码在VS2017的工作中作为更大的代码库的一部分工作,但是当我在家中与VS2017隔离时,它失败并出现与GCC相同的错误.
你可以尝试在这里编译它:
sqlite3_reset()调用失败后是否需要调用准备好的语句sqlite3_step()?我正在使用 sqlite3 版本 3.23.1。我准备好的语句的生命周期如下:
sqlite3_prepare_v2()并保留准备好的语句的句柄在应用程序的生命周期内可用。sqlite3_bind_*()函数,然后执行sqlite3_step()该语句,直到得到SQLITE_ROW除返回之外的其他内容。这是我调用后发生的代码部分sqlite3_step()。请注意,变量resultCode保存最后一次调用的返回值sqlite3_step()。
if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW)
{
if (sqlite3_reset(m_statement) != SQLITE_OK)
{
LogDbFailure(*m_db, "sqlite3_reset()");
}
}
else
{
LogDbFailure(*m_db, "sqlite3_step()");
success = false;
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果对步骤的调用失败,我不会进行重置。Google 上的文档或搜索结果中没有任何内容表明sqlite3_reset()必须在失败时调用。事实上,文档指出,sqlite3_reset()失败后调用也会失败:
如果最近对准备好的语句 S 的 sqlite3_step(S) 调用指示错误,则 sqlite3_reset(S) 返回适当的错误代码。
读到这篇文章让我觉得如果步骤失败,也许我不应该调用重置函数。
谁能澄清一下吗?请注意,就我而言,sqlite3_step()失败是因为SQLITE_BUSY. 我正在使用 WAL 日志模式。一旦准备好的语句上的步骤失败,当我调用 时,该准备好的语句将永远处于繁忙状态sqlite3_step()。sqlite3_bind_*()return …
受到这个问题的启发:*(&arr + 1) - arr 如何给出数组 arr 元素的长度?
以下代码将计算数组的长度,尽管调用了未定义的行为:
int arr[] = {5, 8, 1, 3, 6};
size_t len = *(&arr + 1) - &arr[0]; // len is 5
Run Code Online (Sandbox Code Playgroud)
我相信,通过取消引用 (&arr + 1) 我们正在触发未定义的行为。但是,我们这样做的唯一原因是立即将结果衰减为int*,指向原始数组中最后一个元素之后的一个元素。由于我们没有取消引用这个指针,我们在定义的区域中很好。
因此,问题如下:是否有一种方法可以在int*不取消引用不可引用指针并保持定义的情况下衰减?
PS 强制免责声明:是的,我可以使用sizeof运算符和除法计算数组的大小。这不是问题的重点。
编辑: 我现在不太确定间接本身是未定义的。我发现http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232从它看起来似乎有试图使间接本身合法化,但我没有能够在实际标准中找到任何与此相关的措辞。
假设我有一个枚举:
typedef enum {
Val1,
Val2,
Val3,
Val4
} vals;
Run Code Online (Sandbox Code Playgroud)
并且函数check(vals x)返回一个布尔值,指示val是否在特定的值子集中vals.
bool check(vals x) {
switch(x) {
case Val1:
case Val3:
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我想使用这个函数作为enable_if(函数,你可以看到,它不是一个函数,取决于运行时)的条件,让用户只使用这些值与类模板.
class MyClass<vals v> {
}
Run Code Online (Sandbox Code Playgroud)
PS:我需要模板来为类的方法进行特化,具体取决于模板值.