首先,我想说,根据cppreference.com,对枚举值进行初始化是不可能的.
根据http://en.cppreference.com/w/cpp/language/value_initialization,初始化枚举值实际上执行零初始化.然后,根据http://en.cppreference.com/w/cpp/language/zero_initialization,零初始化枚举的效果是:
如果
T是标量类型,则对象的初始值是隐式转换为的整数常量零T.
但是,整数常数零不能隐式转换为枚举.最终,枚举不能进行价值初始化.这听起来很奇怪,并且枚举值的初始值确实适用于VC,GCC和clang.那么,标准对此有何看法?
其次,根据http://en.cppreference.com/w/cpp/language/static_cast:
整数,浮点或枚举类型可以转换为任何完整的枚举类型(结果是未指定的(直到C++ 17)未定义的行为(自C++ 17)如果表达式的值转换为枚举的基础类型,不是目标枚举值之一)
那么,这是否意味着如果目标枚举没有枚举器等于,则初始化枚举值(如果它可以工作)可能实际上导致未定义的行为0?
c++ enums initialization language-lawyer value-initialization
例如,
#include <iostream>
int main() {
unsigned n{};
std::cin >> n;
std::cout << n << ' ' << (bool)std::cin << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
输入时-1,clang 6.0.0输出,0 0而gcc 7.2.0输出4294967295 1.我想知道谁是对的.或者两者都是正确的标准没有指定这个?如果失败,我认为(bool)std::cin被评估为假.clang 6.0.0也输入失败-0.
在cppref中,以下内容一直持续到C++ 17:
f(std::shared_ptr<int>(new int(42)), g())如果g在之后调用new int(42)并抛出异常,则可能导致内存泄漏的代码,同时f(std::make_shared<int>(42), g())是安全的,因为两个函数调用永远不会交错.
我想知道在C++ 17中引入了哪些更改使其不再适用.
这里列出了std::absC++ 中的当前重载.我想知道为什么不定义以下模板并放弃所有丑陋的C风格重载?
template <typename T> inline
T abs(const T& v) { return v < 0 ? -v : v; }
Run Code Online (Sandbox Code Playgroud) 使用T[][][]语法定义多维数组很容易.但是,这会创建一个原始数组类型,它不适合现代C++.这就是我们std::array从C++ 11开始的原因.但是使用多维数组来定义多维数组的语法std::array非常混乱.例如,要定义三维int数组,您必须编写std::array<std::array<std::array<int, 5>, 5>, 5>.语法根本不可扩展.我要求解决这个问题.也许,使用C++提供的现有实用程序无法修复此问题.在这种情况下,我很高兴开发了一种自定义工具来简化语法.
自己找到了解决方案:
template <typename T, std::size_t n, std::size_t... ns>
struct multi_array {
using type = std::array<typename multi_array<T, ns...>::type, n>;
};
template <typename T, std::size_t n>
struct multi_array<T, n> {
using type = std::array<T, n>;
};
template <typename T, std::size_t... ns>
using multi_array_t = typename multi_array<T, ns...>::type;
Run Code Online (Sandbox Code Playgroud)
想知道是否可以进一步简化实施.
c++ arrays multidimensional-array template-meta-programming c++14
我所说的意思可以通过以下示例来解释:
auto p = std::make_shared<int>();
在int可变缺省初始化(因此具有垃圾值)或值初始化(从而具有零的值)?我已经在GCC 5.2和clang 3.6上进行了测试,前者进行了值初始化,后者进行了默认初始化.我想知道标准对此有何看法?在我看来,现代C++肯定应该在这种情况下执行值初始化.
使用以下代码可以清楚地解决该问题:
#include <functional>
#include <iostream>
#include <vector>
int main() {
//std::vector<int> a, b;
int a = 0, b = 0;
auto refa = std::ref(a);
auto refb = std::ref(b);
std::cout << (refa < refb) << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用注释std::vector<int> a, b;而不是int a = 0, b = 0;,则代码不会在GCC 5.1,clang 3.6或MSVC'13中的任何一个上编译.在我看来,std::reference_wrapper<std::vector<int>>可以隐式转换std::vector<int>&为LessThanComparable,因此它应该是LessThanComparable本身.有人可以向我解释一下吗?
c++ language-lawyer implicit-conversion c++11 reference-wrapper
以下肯定有效,但非常繁琐:
T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;
Run Code Online (Sandbox Code Playgroud)
我正试图发现最简洁的方式.以下工作会吗?
T& operator=(T) = delete;
Run Code Online (Sandbox Code Playgroud)
更新
请注意,我选择T& operator=(T)而不是T& operator=(const T&)或T& operator=(T&&),因为它可以同时满足两个目的.
有问题的代码是
#include <functional>
#include <utility>
template <typename F>
void for_each(F&&) noexcept {}
template <typename F, typename T, typename... Us>
void for_each(F&& f, T&& v, Us&&... us) {
std::invoke(std::forward<F>(f), std::forward<T>(v));
for_each(std::forward<F>(f), std::forward<Us>(us)...);
}
void func(void*) noexcept {}
int main() {
for_each(func, nullptr);
}
Run Code Online (Sandbox Code Playgroud)
它在gcc 8上编译,但在clang 6上失败,出现以下错误:
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4198:19: error: invalid application of 'sizeof' to a function type
static_assert(sizeof(_Tp) > 0, "Type must be complete.");
^~~~~~~~~~~
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4203:15: note: in instantiation of template class 'std::__1::__check_complete<void (void *) noexcept>' …Run Code Online (Sandbox Code Playgroud) 例如,而不是
void shared_ptr::reset() noexcept;
template <typename Y>
void shared_ptr::reset(Y* ptr);
Run Code Online (Sandbox Code Playgroud)
人们可能会想到
template <typename Y = T>
void shared_ptr::reset(Y* ptr = nullptr);
Run Code Online (Sandbox Code Playgroud)
我认为这里的性能差异可以忽略不计,第二个版本更简洁.有没有具体的原因C++标准是第一种方式?
在同样的问题已经被问了科特林语言,默认参数为首选那里.
更新:
std::unique_ptr::reset()遵循默认参数设计(参见此处).所以我认为std::shared_ptr::reset()使用重载的原因是因为它们有不同的异常规范.
c++ api-design overloading language-lawyer default-arguments