小编Ell*_*ith的帖子

处理一般情况混合类型和非类型的可变参数模板

所以我试图创建一个类型特征,说明两个“外部”类类型是否相同。

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

10
推荐指数
1
解决办法
273
查看次数

传递重载函数指针及其参数时的错误类型推导

我正在尝试提供一个包装器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

8
推荐指数
1
解决办法
158
查看次数

std :: set <int*const>不会编译

这里的"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)

c++ pointers const stdset

7
推荐指数
2
解决办法
306
查看次数

有没有一种有效的方法可以在转换后使用views::filter?(范围适配器)

奇怪行为的常见示例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)

...只是语法糖: …

c++ gcc g++ c++20 std-ranges

5
推荐指数
1
解决办法
4418
查看次数

是否有一种安全(定义的行为)方法来使用 STL 来减少基于向量索引有效过滤向量的样板?

我经常发现自己想要根据向量的索引而不是值来过滤向量。

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)

c++ stl erase-remove-idiom stl-algorithm c++20

5
推荐指数
1
解决办法
293
查看次数

为什么“保证复制消除”不意味着 push_back({arg1, arg2}) 与 emplace_back(arg1, arg2) 相同?

首先,我听说“保证复制消除”是一个用词不当(据我目前的理解,它更多的是从根本上重新定义基本值类别,从 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();,纯右值将实现一个临时值(使用 …

c++ language-lawyer copy-elision c++17 prvalue

4
推荐指数
1
解决办法
127
查看次数

Is using enum class for flags undefined behavior?

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 …

c++ undefined-behavior enum-class c++20

3
推荐指数
1
解决办法
245
查看次数

获取自分支以来所有已编辑文件的列表

我想获得自主分支分支以来已编辑文件的列表(不是与主分支的最新头进行比较,而是与分支点的主分支进行比较)。

这可能吗?

这似乎是一件很常见的事情,但我的同事不知道 git 命令,也没有在网上找到任何东西(我猜用谷歌搜索有点困难)。

git git-branch git-history

2
推荐指数
1
解决办法
99
查看次数

为什么使用默认构造函数“{}”而不是“= default”会导致性能变化?

我最近注意到我的性能受到了影响,因为我声明了一个默认构造函数,例如:

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

1
推荐指数
1
解决办法
206
查看次数