小编Vit*_*meo的帖子

删除右值,保持左值引用(标准类型特征可用吗?)

我正在尝试编写一个函数,该函数以一个形式返回一个可变参数包的子集std::tuple.理想情况下,该函数不应具有运行时开销(没有不必要的副本),并且应该允许用户访问lvalue引用并修改它们.

应保持值类型,lvalue引用和const lvalue引用.Temporaries(rvalue引用)应该"转换"为值类型,以避免创建无效引用(对临时引用的引用).

期望结果的示例:

int lr = 5;
const int& clr = lr;

auto t = make_subpack_tuple(lr, clr, 5);

static_assert(is_same
<
    decltype(t), 
    std::tuple<int&, const int&, int>
>{}, "");

// Ok, modifies lr:
std::get<0>(t) = 10;

// Compile-time error, intended:
// std::get<1>(t) = 20;

// Ok, 5 was moved into the tuple:
std::get<2>(t) = 30;
Run Code Online (Sandbox Code Playgroud)

示例不完整实施:

template<typename... Ts>
auto make_subpack_tuple(Ts&&... xs)
{
    return std::tuple
    <
        some_type_trait<decltype(xs)>...
    >
    (
        std::forward<decltype(xs)>(xs)...
    );
} …
Run Code Online (Sandbox Code Playgroud)

c++ type-traits rvalue-reference perfect-forwarding c++14

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

组合std :: forward,std :: move和volatile时出现意外的返回类型

上gcc.godbolt.org.

我创建了一个简单的类型特征来删除右值引用:

template <typename T>
struct remove_rvalue_reference { using type = T; };

template <typename T>
struct remove_rvalue_reference<T&&> { using type = T; };

template <typename T>
using remove_rvalue_reference_t = 
    typename remove_rvalue_reference<T>::type;
Run Code Online (Sandbox Code Playgroud)

我用它来实现一个copy_if_rvalue(x)函数,其返回类型取决于传递的参数:

template <typename T>
constexpr auto copy_if_rvalue(T && x) 
  -> remove_rvalue_reference_t<decltype(std::forward<decltype(x)>(x))>
{
    return std::forward<decltype(x)>(x);
}
Run Code Online (Sandbox Code Playgroud)

为了确保函数返回正确的类型,我编写了一些简单的静态断言:

// literal
static_assert(std::is_same<
    decltype(copy_if_rvalue(0)), int
>{});

// lvalue
int lv = 10;
static_assert(std::is_same<
    decltype(copy_if_rvalue(lv)), int&
>{});

// const lvalue
const int clv = 10;
static_assert(std::is_same<
    decltype(copy_if_rvalue(clv)), const int& …
Run Code Online (Sandbox Code Playgroud)

c++ decltype language-lawyer trailing-return-type c++14

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

捕获和调试无效使用对移动的lambda内部的局部变量的引用

我在我的一个真实项目中遇到了一个难以调试的情况,我不小心访问了已被移动的lambda中的局部变量的引用.访问是从另一个线程完成的,但移动的lambda保持活着直到第二个线程完成.

该错误仅在禁用优化时发生,并且是由粗心重构引起的.

我创建了一个最小的例子(可在wandbox上找到),它可以重现这个问题:

struct state
{
    int x = 100;
};

template <typename TF>
void eat1(TF&& f)
{
    // Call the lambda.
    f();

    // Simulate waiting for the second thread
    // to finish.
    std::this_thread::sleep_for(1000ms);
}

template <typename TF>
void eat0(TF&& f)
{
    // Move the lambda to some other handler.
    eat1(std::forward<TF>(f));
}

void use_state(state& s)
{
    // Will print `100`.
    std::cout << s.x << "\n";

    // Separate thread. Note that `s` is captured by
    // reference. …
Run Code Online (Sandbox Code Playgroud)

c++ debugging sanitizer undefined-behavior c++14

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

使用包含不完整类型的`std :: vector`递归定义和访问`boost :: variant` - libstdc ++ vs libc ++

我试图boost::variant使用不完整的包装类和std::vector我的间接技术来定义和访问"递归" .我的实现适用于libstdc ++,但不适用于libc ++.


这是我定义我的变体的方式:

struct my_variant_wrapper;

using my_variant_array = std::vector<my_variant_wrapper>; // <- indirection here
using my_variant = boost::variant<int, my_variant_array>;

struct my_variant_wrapper
{
    my_variant _v;

    template <typename... Ts>
    my_variant_wrapper(Ts&&... xs) : _v(std::forward<Ts>(xs)...) { }
};
Run Code Online (Sandbox Code Playgroud)

std::vector用来引入间接(因此动态分配将阻止my_variant具有无限大小).

由于纸张N4510 ("标准容器的最小不完全类型支持")std::vector<my_variant_wrapper>,我非常有信心我可以使用,哪里my_variant_wrapper不完整的类型:


我随后访问该变体如下:

struct …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-variant libc++ c++17

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

使用fold表达式将参数包扩展为lambda - gcc vs clang

考虑以下代码段:

template <typename TF>
void post(TF){ }

template <typename... TFs>
struct funcs : TFs...
{
    funcs(TFs... fs) : TFs{fs}... { }

    void call() 
    { 
        (post([&]{ static_cast<TFs&>(*this)(); }), ...); 
    }
};
Run Code Online (Sandbox Code Playgroud)

clang ++ 3.8+成功编译代码.

g ++ 7.0无法编译,出现以下错误:

prog.cc: In lambda function:
prog.cc:10:43: error: parameter packs not expanded with '...':
        (post([&]{ static_cast<TFs&>(*this)(); }), ...);
                   ~~~~~~~~~~~~~~~~~~~~~~~~^~
prog.cc:10:43: note:         'TFs'
prog.cc: In member function 'void funcs<TFs>::call()':
prog.cc:10:13: error: operand of fold expression has no unexpanded parameter packs
        (post([&]{ static_cast<TFs&>(*this)(); }), …
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer fold-expression c++17

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

避免并行递归异步算法中的递归模板实例化溢出

这个问题通过一个简化的例子更容易解释(因为我的真实情况远非"最小"):给定...

template <typename T>
void post_in_thread_pool(T&& f) 
Run Code Online (Sandbox Code Playgroud)

...函数模板,我想创建一个具有树状递归结构的并行异步算法.我将使用std::count_if占位符编写下面结构的示例.我将要使用的策略如下:

  • 如果我检查的范围的长度小于64,我将回退到顺序std::count_if功能.(0)

  • 如果它大于或等于64,我将在线程池中生成一个在左半部分递归的作业,并在当前线程上计算该范围的右半部分.(1)

    • 我将使用原子共享int来"等待"计算两半.(2)

    • 我将使用原子共享int来累积部分结果.(3)

简化代码:

auto async_count_if(auto begin, auto end, auto predicate, auto continuation)
{
    // (0) Base case:  
    if(end - begin < 64)
    {
        continuation(std::count_if(begin, end, predicate));
        return;
    }

    // (1) Recursive case:
    auto counter = make_shared<atomic<int>>(2); // (2)
    auto cleanup = [=, accumulator = make_shared<atomic<int>>(0) /*(3)*/]
                   (int partial_result)
    {
        *accumulator …
Run Code Online (Sandbox Code Playgroud)

c++ recursion multithreading asynchronous c++14

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

使用从`std :: tuple`派生的元素在`std :: tuple`上调用`std :: get` - 形成错误?

struct Y { };
struct X : std::tuple<Y> { };

int main()
{
    std::get<0>(std::make_tuple(X{}));
}
Run Code Online (Sandbox Code Playgroud)

在wandbox上


clang++当使用libc ++时,上面的代码编译并按预期工作.

上面的代码失败,都编译clang++g++使用时的libstdc ++,错误如下:

include/c++/7.0.1/tuple:1302:36: 
error: no matching function for call to ‘__get_helper<0>(std::tuple<X>&)’
    { return std::__get_helper<__i>(__t); }
            ~~~~~~~~~~~~~~~~~~~~~~^~~~~

include/c++/7.0.1/tuple:1290:5: 
note: candidate: template<long unsigned int __i, class _Head, class ... _Tail> 
                constexpr _Head& std::__get_helper(std::_Tuple_impl<_Idx, _Head, _Tail ...>&)
    __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
    ^~~~~~~~~~~~

include/c++/7.0.1/tuple:1290:5: 
note:   template argument deduction/substitution failed:
include/c++/7.0.1/tuple:1302:36: 
note:   ‘std::_Tuple_impl<0, _Head, _Tail ...>’ is …
Run Code Online (Sandbox Code Playgroud)

c++ libstdc++ language-lawyer c++11 stdtuple

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

没有通过gcc或clang优化函数指针的间接访问-错误或预期的?

给定以下两个功能:

int f() { return 0; }
int g() { return 1; }
Run Code Online (Sandbox Code Playgroud)

以下代码根据布尔值调用其中之一b

int t0(bool b) { return (b ? &f : &g)(); }
int t1(bool b) { return b ? f() : g(); }
int t2(bool b) { return b ? t0(true) : t0(false); }
Run Code Online (Sandbox Code Playgroud)

两者g++ (trunk)clang++ (trunk)-std=c++2a -Ofast -march=native失败来优化下面的代码:

int main(int ac, char**) { return t0(ac & 1); }
Run Code Online (Sandbox Code Playgroud)

产生以下程序集:

main:
  and edi, 1
  mov eax, OFFSET FLAT:f()
  mov …
Run Code Online (Sandbox Code Playgroud)

c++ optimization function-pointers conditional-operator compiler-optimization

6
推荐指数
0
解决办法
154
查看次数

Using `extern template` to prevent implicit instantiation of a template class

Consider the following code snippet:

template <typename>
struct X { };

extern template struct X<int>;

int main()
{
    X<int>{};
}
Run Code Online (Sandbox Code Playgroud)

It compiles and links: live example on godbolt.org. I would expect it not to link due to the extern template declaration.

My understanding is that extern template means: "please don't instantiate this particular template specialization in this TU, it will be provided by some other TU and you can link against it".

The examples/descriptions. I've seen on isocpp …

c++ templates extern language-lawyer c++11

6
推荐指数
2
解决办法
251
查看次数

尾随返回类型的名称查找和类型简化规则是什么?

尾随返回类型允许在以下两种情况下简化代码:

  1. 从类的成员函数之一返回在类内部定义的类型:

    struct X
    {
        using foo = int;
        foo f();
    };
    
    // pre-C++11
    X::foo X::f()      { /* ... */ }
    
    // trailing, doesn't require `X::` before `foo`
    auto X::f() -> foo { /* ... */ }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 返回复杂的类型,例如函数指针类型:

    // pre-C++11
    int(*g(float))(int) { /* ... */ }
    
    // trailing, easier to read
    auto f(float) -> int(*)(int) { /* ... */ }
    
    Run Code Online (Sandbox Code Playgroud)

我正在尝试查找Standard的相关部分,以解释上述两种简化的工作方式。我已经看过[basic.lookup]并略过了trailing-return,但是找不到任何简单的方法可以解释上述转换的工作原理。

我错过了吗?

标准的哪些部分解释了以上的尾随回返型简化形式?

c++ return-type language-lawyer c++11 trailing-return-type

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