所以我试图创建一个类型特征,说明两个“外部”类类型是否相同。
IE。std::vector<int>与 相同std::vector<double>,我不关心我的类型特征的任何内部参数。
我曾与试图弥补这方面的通用型特质的问题是,我只知道如何处理的类型可变参数模板分别对非类型化的,这似乎从使它通用阻止我。
是否可以处理类型化和非类型化模板参数的任何排列?
这是我实施的内容(包括失败的示例):
// g++ -std=c++17
#include <iostream>
#include <vector>
#include <array>
#include <type_traits>
// If the outer types don't match
template <typename, typename>
struct is_outer_type_same : std::false_type {};
// if the arguments of the compared Type contains only types
// ie. std::vector<int,std::allocator<int>>
// (the inner arguments are also types)
template <template<typename...> typename OuterType,
typename... InnerTypes1,
typename... InnerTypes2
>
struct is_outer_type_same < OuterType<InnerTypes1...>,
OuterType<InnerTypes2...>
>
: std::true_type …Run Code Online (Sandbox Code Playgroud) c++ generic-programming type-traits template-meta-programming variadic-templates
我正在尝试提供一个包装器std::invoke来完成推导函数类型的工作,即使函数已重载。
(我昨天为可变参数和方法指针版本问了一个相关问题)。
当函数有一个参数时,此代码 (C++17) 在正常重载条件下按预期工作:
#include <functional>
template <typename ReturnType, typename ... Args>
using FunctionType = ReturnType (*)(Args...);
template <typename S, typename T>
auto Invoke (FunctionType<S, T> func, T arg)
{
return std::invoke(func, arg);
}
template <typename S, typename T>
auto Invoke (FunctionType<S, T&> func, T & arg)
{
return std::invoke(func, arg);
}
template <typename S, typename T>
auto Invoke (FunctionType<S, const T&> func, const T & arg)
{
return std::invoke(func, arg);
}
template <typename S, …Run Code Online (Sandbox Code Playgroud) c++ templates function-pointers template-meta-programming type-deduction
这里的"const"是编译问题的原因.但是,自己实现了STL树,我无法理解为什么.
这是代码:
#include <iostream>
#include <set>
int main ()
{
int a;
// I want the set to carry the "promise"
// to keep the pointers constant
std :: set < int * const > x;
x . insert ( &a );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
In file included from /usr/include/c++/7/string:48:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from demo.cpp:1:
/usr/include/c++/7/bits/stl_function.h: In instantiation of ‘struct std::_Identity<int* const>’:
/usr/include/c++/7/bits/stl_tree.h:2091:29: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) …Run Code Online (Sandbox Code Playgroud) 奇怪行为的常见示例views::filter:
#include <iostream>
#include <ranges>
#include <vector>
int main ()
{
using namespace std;
auto ml = [](char c) // ml = make lambda (always accepts / transforms to 1)
{
return [c](int) {cout << c; return 1;};
};
vector<int> vec = {1};
auto view = vec
| views::transform (ml('T'))
| views::filter (ml('F'));
// use view somehow:
return *view.begin();
}
Run Code Online (Sandbox Code Playgroud)
哪个输出TFT(注意额外的T)。演示
我们必须知道:
auto view = vec
| views::transform (ml('A'))
| views::filter (ml('B'));
Run Code Online (Sandbox Code Playgroud)
...只是语法糖: …
我经常发现自己想要根据向量的索引而不是值来过滤向量。
auto some_values = std::vector{1, 0, 4, 6, 2};
// Somewhere I figure out which items to remove.
// This may be from user interaction or something
// nothing to do with the original values:
const auto removing = std::vector<bool>{0, 0, 1, 0, 1};
Run Code Online (Sandbox Code Playgroud)
erase_if所以,我很想像这样使用:
std::erase_if(some_values, [it = removing.begin()](auto) mutable {return *it++;});
Run Code Online (Sandbox Code Playgroud)
它似乎适用于 gcc 和 clang。但是, std::erase cppref 页面上似乎没有任何关于谓词调用顺序的内容,所以我认为这是未定义的行为?
与 相同的问题std::remove_if。请注意,压缩范围不适用于大多数压缩选项,因为通常生成的范围无法调整基础数据的大小。
使用 for 循环并创建数组的副本并不是太多的样板文件,但我目前正在将过滤器应用于一些低级代码,在这些代码中我无法复制所有数据。有些数据会很大,需要在这些过滤操作期间做出响应。
最坏的情况我可以添加这样的函数来解决问题:
template <class T, auto N, class Pred>
size_t …Run Code Online (Sandbox Code Playgroud) 首先,我听说“保证复制消除”是一个用词不当(据我目前的理解,它更多的是从根本上重新定义基本值类别,从 r/l 值到 l/x/pr 值,这从根本上改变了含义和副本的要求),但由于这就是通常所说的,我也会。
在阅读了有关这个主题的一些内容后,我想我终于理解了它 - 至少足以认为:
my_vector.push_back({arg1, arg2});
Run Code Online (Sandbox Code Playgroud)
从 c++17 开始,相当于:
my_vector.emplace_back(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)
我最近试图说服我的同事这一点。唯一的问题是他告诉我我完全错了!他编写了一些 godbolt 代码(如下所示),其中程序集显示push_back创建了一个临时文件,该临时文件被移入向量中。
因此,为了完成我的问题,我必须首先证明这里存在一些令人困惑的原因。我将引用关于这个主题的备受推崇的 stackoverflow 答案(强调我的):
保证复制省略重新定义了纯右值表达式的含义。[...]纯右值表达式只是可以实现临时值的东西, 但它还不是临时值。
如果使用纯右值来初始化该纯右值类型的对象, 则不会具体化临时值。[...]
需要理解的是,由于返回值是纯右值, 因此它还不是对象。它只是一个对象的初始化器[...]
就我而言,我认为auto il = {arg1, arg2}会调用 for 的构造函数std::initializer_list,但{arg1, arg2}inpush_back({arg1, arg2})将是纯右值(因为它未命名),因此将是向量元素的初始化器,而无需对其进行初始化。
当你执行 T t = Func(); 时,返回值的纯右值直接初始化对象 t;没有“创建临时和复制/移动”阶段。由于 Func() 的返回值是与 T() 等效的纯右值,因此 t 直接由 T() 初始化,就像执行 T t = T() 一样。
如果以任何其他方式使用纯右值,则纯右值将具体化一个临时对象,该对象将在该表达式中使用(如果没有表达式,则将其丢弃)。因此,如果您执行 const T &rt = Func();,纯右值将实现一个临时值(使用 …
I've been using overloaded operators as demonstrated in the second answer from here: How to use C++11 enum class for flags ... example:
#define ENUMFLAGOPS(EnumName)\
[[nodiscard]] __forceinline EnumName operator|(EnumName lhs, EnumName rhs)\
{\
return static_cast<EnumName>(\
static_cast<std::underlying_type<EnumName>::type>(lhs) |\
static_cast<std::underlying_type<EnumName>::type>(rhs)\
);\
}...(other operator overloads)
enum class MyFlags : UINT //duplicated in JS
{
None = 0,
FlagA = 1,
FlagB = 2,
FlagC = 4,
};
ENUMFLAGOPS(MyFlags)
Run Code Online (Sandbox Code Playgroud)
...
MyFlags Flags = MyFlags::FlagA | MyFlags::FlagB;
Run Code Online (Sandbox Code Playgroud)
And I've grown concerned that this may be …
我想获得自主分支分支以来已编辑文件的列表(不是与主分支的最新头进行比较,而是与分支点的主分支进行比较)。
这可能吗?
这似乎是一件很常见的事情,但我的同事不知道 git 命令,也没有在网上找到任何东西(我猜用谷歌搜索有点困难)。
我最近注意到我的性能受到了影响,因为我声明了一个默认构造函数,例如:
Foo() = default;
Run Code Online (Sandbox Code Playgroud)
代替
Foo() {}
Run Code Online (Sandbox Code Playgroud)
(仅供参考,我需要明确声明它,因为我还有一个可变参数构造函数,否则会覆盖默认构造函数)
这对我来说似乎很奇怪,因为我认为这两行代码是相同的(好吧,只要默认构造函数是可能的。如果默认构造函数不可用,第二行代码会产生错误,第一行会产生错误)隐式删除默认构造函数。'不是我的情况!)。
好的,所以我做了一个小测试器,结果根据编译器的不同而有很大差异,但是在某些设置下,我得到了一致的结果,一个比另一个更快:
#include <chrono>
template <typename T>
double TimeDefaultConstructor (int n_iterations)
{
auto start_time = std::chrono::system_clock::now();
for (int i = 0; i < n_iterations; ++i)
T t;
auto end_time = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end_time - start_time;
return elapsed_seconds.count();
}
template <typename T, typename S>
double CompareDefaultConstructors (int n_comparisons, int n_iterations)
{
int n_comparisons_with_T_faster = 0;
for (int i = 0; i < n_comparisons; ++i)
{
double time_for_T = TimeDefaultConstructor<T>(n_iterations);
double time_for_S …Run Code Online (Sandbox Code Playgroud) c++ performance constructor default-constructor compiler-optimization
c++ ×8
c++20 ×3
c++17 ×1
const ×1
constructor ×1
copy-elision ×1
enum-class ×1
g++ ×1
gcc ×1
git ×1
git-branch ×1
git-history ×1
performance ×1
pointers ×1
prvalue ×1
std-ranges ×1
stdset ×1
stl ×1
templates ×1
type-traits ×1