C++20 允许使用auto
函数参数类型。
它是否还允许auto
用作函数参数类型的模板参数占位符(不相似,但在某种程度上符合C++17 template<auto>的精神)?
所以下面的代码,在 C++20 之前:
template<typename First, typename Second>
void printPair(const std::pair<First, Second>& p) {
std::cout << p.first << ", " << p.second;
}
Run Code Online (Sandbox Code Playgroud)
可以写成:
void printPair(const std::pair<auto, auto>& p) {
std::cout << p.first << ", " << p.second;
}
Run Code Online (Sandbox Code Playgroud)
它确实可以编译并与概念的实验性 GCC 实现一起很好地工作。
它是 C++20 的合法语法吗?
// #1
template <typename T, T n1, T n2>
struct foo {
static const char* scenario() {
return "#1 the base template";
}
};
// #2
// partial specialization where T is unknown and n1 == n2
template <typename T, T a>
struct foo<T, a, a> {
static const char* scenario() {
return "#2 partial specialization";
}
};
Run Code Online (Sandbox Code Playgroud)
下面的主要内容在g ++(6.1)和clang ++(3.8.0)上有不同的结果:
extern const char HELLO[] = "hello";
double d = 2.3;
int main() {
cout << foo<int, 1, 2> …
Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization template-specialization
在使用可变参数模板时,遵循这个SO问题(注意:并不是强制要求遵循这个问题),对于以下模板重载函数,我得到了clang(3.8)和g ++(6.1)的不同行为:
template <class... Ts>
struct pack { };
template <class a, class b>
constexpr bool starts_with(a, b) {
return false;
}
template <template <typename...> class PACK_A,
template <typename...> class PACK_B, typename... Ts1, typename... Ts2>
constexpr bool starts_with(PACK_A<Ts1..., Ts2...>, PACK_B<Ts1...>) {
return true;
}
int main() {
std::cout << std::boolalpha;
std::cout << starts_with(pack<int, float, double>(),
pack<float, int, double>()) << std::endl;
std::cout << starts_with(pack<int, float, double>(),
pack<int, float, double, int>()) << std::endl;
std::cout << starts_with(pack<int, float, double>(),
pack<int, float, …
Run Code Online (Sandbox Code Playgroud) 以下代码导致对哈希函数的无法解释的调用:
namespace foo {
using Position = tuple <int, int, int>;
std::ostream& operator<<(std::ostream& out, const Position& pos) noexcept{
return out << get<0>(pos) << ", " << get<1>(pos) << ", " << get<2>(pos);
}
struct hashFunc{
std::size_t operator()(const Position& pos) const noexcept{
int res = get<0>(pos) * 17 ^ get<1>(pos) * 11 ^ get<2>(pos);
cout << "@@@ hash function called for key: " << pos
<< ", hash: " << res << endl;
return res;
}
};
template<typename T>
void print_buckets(T&& …
Run Code Online (Sandbox Code Playgroud) 我在http://en.cppreference.com/w/cpp/language/operators上读到:
布尔逻辑运算符,运算符&&和运算符||
与内置版本不同,重载不会在右操作数之前对其左操作数进行排序,并且(直到C++ 17)无法实现短路评估.
(我强调).
找不到C++ 17的任何资源或代码示例,支持运算符&&和operator ||的短路.它与C++ 17参数包折叠表达式有关吗?尝试使用它,但无法为重载的运算符&&和||创建短路行为 用C++ 17倍表达式.
码:
class A {
bool val;
public:
A(bool b) : val(b) { cout << "A born as " << boolalpha << val << endl;}
template<typename ...Args>
bool operator&&(Args&&... args) {
return (val && ... && args.val);
}
};
int main() {
cout << boolalpha;
cout << ( A{false} && A{true} ) << endl;
cout << ( A{true} && A{false} ) << endl;
cout << ( …
Run Code Online (Sandbox Code Playgroud) 以下代码可以使用 MSVC 进行编译,但在 GCC 和 Clang 中会失败,因为typename
在依赖类型之前缺少:
struct Foo { struct value{ }; };
struct Bar { int value; };
template<typename T>
constexpr size_t SIZE = sizeof(T::value); // missing typename here, for Foo
constexpr size_t s1 = SIZE<Foo>; // missing typename before dependent type above
constexpr size_t s2 = SIZE<Bar>;
Run Code Online (Sandbox Code Playgroud)
MSVC 方法不需要 typename sizeof
,这似乎是合理的,因为 sizeof 对类型和变量都适用。另一方面,GCC 和 Clang 似乎按规矩办事,因为这是typename
即使在 C++20 中您仍然需要的情况之一,当上下文无法向编译器显示它是否会满足类型或多变的。
问题是这里MSVC是否允许宽容,即编译器如果不加 也能正确执行所需的操作typename
,是否允许这样做?还是与规范相矛盾?
MSVC 与 Clang 和 GCC 的方法之间的差异在于以下代码 …
添加了 C++20 std::to_array
,因此您可以轻松地从 C 样式数组创建std::array
,例如:
template<typename T, std::size_t N>
void foo(const T (&a)[N]) {
auto arr = std::to_array(a);
}
Run Code Online (Sandbox Code Playgroud)
但是,std::to_array
不支持二维数组,因此以下方法不起作用:
auto arr = to_array({1, 2}, {3, 4});
Run Code Online (Sandbox Code Playgroud)
这可以手动实现吗?
从“死”的unique_ptr中使用operator *的返回值是不好的。
以下代码可以编译,但是结果当然是未定义行为:
auto& ref = *std::make_unique<int>(7);
std::cout << ref << std::endl;
Run Code Online (Sandbox Code Playgroud)
为什么标准不将std :: unique_ptr 右值的operator *的返回值设为内部值的右值,而不是像这样的lvalue:
// could have been done inside unique_ptr
T& operator*() & { return *ptr; }
T&& operator*() && { return std::move(*ptr); }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,可以正常工作:
std::cout << *std::make_unique<int>(7) << std::endl;
Run Code Online (Sandbox Code Playgroud)
但是开头的代码无法编译(无法将右值绑定到左值)。
旁注:当然,有些人仍然可以像下面这样编写错误的代码,但是更冗长地说“我是UB”,因此不太相关:
auto&& ref = *std::make_unique<int>(7);
std::cout << ref << std::endl;
Run Code Online (Sandbox Code Playgroud)
这是来自 C++20 规范 ( [basic.life]/8 )的代码示例:
struct C {
int i;
void f();
const C& operator=( const C& );
};
const C& C::operator=( const C& other) {
if ( this != &other ) {
this->~C(); // lifetime of *this ends
new (this) C(other); // new object of type C created
f(); // well-defined
}
return *this;
}
int main() {
C c1;
C c2;
c1 = c2; // well-defined
c1.f(); // well-defined; c1 refers to a new object of type …
Run Code Online (Sandbox Code Playgroud) 在 C++20 或 range-TS 中是否有一个已经定义的概念来指定特定类型的范围?
就像是:
template < class T, class InnerType >
concept RangeOf =
requires(T&& t) {
requires std::same_as<
std::remove_cvref_t<decltype(*std::ranges::begin(t))>,
InnerType
>;
std::ranges::end(t);
};
Run Code Online (Sandbox Code Playgroud)
允许,例如:
void print(const RangeOf<char> auto& char_seq) { /* ... */ }
Run Code Online (Sandbox Code Playgroud) c++ ×10
c++20 ×5
templates ×3
c++11 ×2
algorithm ×1
auto ×1
c++-concepts ×1
c++17 ×1
overloading ×1
std-ranges ×1
stdarray ×1
stdlaunder ×1
typename ×1
unique-ptr ×1