假设我们想通过以下方式声明const成员函数typedef:
typedef int FC() const;
typedef int F();
struct A
{
FC fc; // fine, we have 'int fc() const'
const F fc; // not fine, 'const' is ignored, so we have 'int fc()'
};
Run Code Online (Sandbox Code Playgroud)
由于const被忽略,程序编译得很好.为什么const忽略功能?既然我们可以用这种方式形成const指针,我唯一能想到的就是"C传承".标准是否对此有所说明?
我发现对类使用初始化列表语法的可能性取决于类字段是否具有默认值.为什么?
确切地说,请考虑以下代码:
class S
{
public:
int a;
};
...
int a;
S s{ a };
Run Code Online (Sandbox Code Playgroud)
它编译没有任何问题.但是如果我在类字段中添加一个默认值,它就会停止构建:
class S
{
public:
int a = 0;
};
...
int a;
S s{ a };
Run Code Online (Sandbox Code Playgroud)
错误1错误C2440:'初始化':无法从'initializer-list'转换为'S'
为什么?还有什么影响这样的构造函数生成?
我正在尝试编写一个可变参数模板constexpr函数,它可以计算给定模板参数的总和.这是我的代码:
template<int First, int... Rest>
constexpr int f()
{
return First + f<Rest...>();
}
template<int First>
constexpr int f()
{
return First;
}
int main()
{
f<1, 2, 3>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,error C2668: 'f': ambiguous call to overloaded function在尝试解析f<3,>()调用时,它不会编译报告错误消息.
我还尝试将我的递归基础案例更改为接受0模板参数而不是1:
template<>
constexpr int f()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码也没有编译(消息error C2912: explicit specialization 'int f(void)' is not a specialization of a function template).
我可以提取第一个和第二个模板参数来进行编译和工作,如下所示:
template<int First, int Second, int... Rest>
constexpr int …Run Code Online (Sandbox Code Playgroud) 在编写C++代码时,我突然意识到我的数字被错误地转换double为unsigned long long.
具体来说,我使用以下代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <limits>
using namespace std;
int main()
{
unsigned long long ull = numeric_limits<unsigned long long>::max();
double d = static_cast<double>(ull);
unsigned long long ull2 = static_cast<unsigned long long>(d);
cout << ull << endl << d << endl << ull2 << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的计算机上执行此代码时,我有以下输出:
18446744073709551615
1.84467e+019
9223372036854775808
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)
我期望第一个和第三个数字完全相同(就像在Ideone上一样),因为我确信它long double占用了10个字节,并将尾数存储在其中的8个中.我会理解,如果第三个数字与第一个数字相比被截断 - 只是因为浮点数格式的错误.但这里的价值是两倍不同!
所以,主要的问题是:为什么?我怎样才能预测出这种情况呢?
一些细节:我在Windows 7上使用Visual Studio …
在阅读Bjarne Stroustrup的CoreCppGuidelines时,我找到了一条与我的经历相矛盾的指南.
该C.21要求如下:
如果您定义或
=delete任何默认操作,请定义或=delete全部
原因如下:
特殊函数的语义密切相关,因此如果需要非默认函数,则其他人也需要修改.
根据我的经验,重新定义默认操作的两种最常见情况如下:
#1:使用默认主体定义虚拟析构函数以允许继承:
class C1
{
...
virtual ~C1() = default;
}
Run Code Online (Sandbox Code Playgroud)
#2:默认构造函数的定义,对RAII类型的成员进行一些初始化:
class C2
{
public:
int a; float b; std::string c; std::unique_ptr<int> x;
C2() : a(0), b(1), c("2"), x(std::make_unique<int>(5))
{}
}
Run Code Online (Sandbox Code Playgroud)
根据我的经验,所有其他情况都很少见.
您如何看待这些例子?它们是C.21规则的例外,还是最好在这里定义所有默认操作?还有其他常见的例外吗?
我正在编写一个用户定义的string文字来将月份名称转换为数字.这个文字的预期用法是这样的
"Nov"_m
Run Code Online (Sandbox Code Playgroud)
应该返回11.
目前我的代码看起来像
constexpr Duration operator ""_m(const char* str, size_t len)
{
return convert_month_to_int(str, len);
}
Run Code Online (Sandbox Code Playgroud)
where constexpr int convert_month_to_int(const char, size_t)是一个执行实际转换的函数(-1如果月份名称不正确则返回).
问题是,如果传递给此文字的字符串没有任何月份的名称,我想显示某种编译错误.我尝试使用static_assert以下方式:
constexpr Duration operator ""_m(const char* str, size_t len)
{
static_assert(convert_month_to_int(str, len) > 0, "Error");
return convert_month_to_int(str, len);
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为编译器不确定它convert_month_to_int(str, len)是一个常量表达式.
有没有办法实现这种行为?
在微软实施指南支持库中我看到以下代码:
template<class T>
class not_null {
...
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u)) {
Expects(ptr_ != nullptr);
}
...
constexpr T get() const {
Ensures(ptr_);
return ptr_;
}
...
T ptr_;
}
Run Code Online (Sandbox Code Playgroud)
所有gsl::not_null可能采用指针的构造函数都会检查这些指针是否为空,但我们仍然在每次ptr_取消引用时检查指针 ( ) 的存储值是否为空。鉴于在 C++ 中我们通常不会为不需要的东西付费,为什么我们要进行此检查?
UP:确保按如下方式实现(使用默认标志):
#define GSL_LIKELY(x) (!!(x))
...
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
...
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
Run Code Online (Sandbox Code Playgroud) 我可以制作仅头文件的库,例如 dll 和 lib 文件的 boost 吗?
环境:Window 10,Visual Studio 2015,Cmake
#include <iostream>
void ArraySize(int arrMyarr[])
{
std::cout << sizeof(arrMyarr) << '\n';
}
void ArraySize1(int *arrMyarr)
{
std::cout << sizeof(arrMyarr) << '\n';
}
int main()
{
int arrTemp[] = { 122, 11, 22, 63, 15, 78, 143, 231 };
std::cout << sizeof(arrTemp) << '\n';
ArraySize(arrTemp);
ArraySize1(arrTemp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:32 4 4
以下两个函数声明是否相同?
void ArraySize(int arrMyarr[]);
void ArraySize1(int *arrMyarr);
在这个问题中,它表明不可能直接使用模板参数用于类构造函数,因为如果你写了类似的东西
struct S{
template<typename T>
S() { ... }
}
Run Code Online (Sandbox Code Playgroud)
然后你无法调用这个构造函数.但是,有一些解决方法可以使这项工作,例如,通过模板参数推导.
但我所知道的所有这些变通办法都只适用于类型参数.所以,问题是
是否有任何变通方法可以使这种方法适用于非类型模板参数?
struct S{
template<int x>
S() { ... }
}
Run Code Online (Sandbox Code Playgroud)
我对能够在现代C++(C++ 17标准,包括所有TS)中工作的解决方案感兴趣,因为这是一个理论而非实际的问题.