I have this code where I have a class MyElement
that holds a MyData<UnderlyingData>
that's constructed during the constructor:
#include <atomic>
#include <iostream>
#include <vector>
struct UnderlyingData {
int a;
int b;
UnderlyingData(int _a, int _b) : a(_a), b(_b) {}
};
template <typename T> class MyData {
public:
std::atomic<T> data_;
template <typename... Args>
MyData(Args &&...args) : data_(T(std::forward<Args>(args)...)) {}
};
class MyElement {
public:
int c;
MyData<UnderlyingData> mydata;
explicit MyElement(int _c) : c(_c), mydata(0, 6) {}
};
int main() {
std::vector<MyElement> arr;
arr.emplace_back(5);
std::cout << arr.at(0).c << " " << arr.at(0).mydata.data_.load().a << " "
<< arr.at(0).mydata.data_.load().b << "\n";
return 0;
}
As you can see, MyData<UnderlyingData>
holds an atomic<UnderlyingData>
and the constructor of MyData
attempts to perfect forward to the UnderlyingData
through the atomic. This code works if I try to construct a MyData<UnderlyingData>
variable manually, or a MyElement
variable, like this:
MyElement element(5);
std::cout << element.c << " " << element.mydata.data_.load().b << "\n";
However, when I put MyElement
into a vector and use either emplace_back
or push_back(MyElement(5))
, I get this cryptic error:
test.cpp: In instantiation of ‘MyData<T>::MyData(Args&& ...) [with Args = {MyData<UnderlyingData>}; T = UnderlyingData]’:
test.cpp:20:7: required from ‘void std::_Construct(_Tp*, _Args&& ...) [with _Tp = MyElement; _Args = {MyElement}]’
/usr/include/c++/11/bits/stl_uninitialized.h:92:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MyElement*>; _ForwardIterator = MyElement*; bool _TrivialValueTypes = false]’
/usr/include/c++/11/bits/stl_uninitialized.h:151:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MyElement*>; _ForwardIterator = MyElement*]’
/usr/include/c++/11/bits/stl_uninitialized.h:333:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<MyElement*>; _ForwardIterator = MyElement*; _Tp = MyElement]’
/usr/include/c++/11/bits/stl_uninitialized.h:355:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = MyElement*; _ForwardIterator = MyElement*; _Allocator = std::allocator<MyElement>]’
/usr/include/c++/11/bits/vector.tcc:474:3: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {int}; _Tp = MyElement; _Alloc = std::allocator<MyElement>; std::vector<_Tp, _Alloc>::iterator = std::vector<MyElement>::iterator]’
/usr/include/c++/11/bits/vector.tcc:121:21: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = MyElement; _Alloc = std::allocator<MyElement>; std::vector<_Tp, _Alloc>::reference = MyElement&]’
test.cpp:30:19: required from here
test.cpp:17:34: error: no matching function for call to ‘UnderlyingData::UnderlyingData(MyData<UnderlyingData>)’
17 | MyData(Args &&...args) : data_(T(std::forward<Args>(args)...)) {}
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:9:3: note: candidate: ‘UnderlyingData::UnderlyingData(int, int)’
9 | UnderlyingData(int _a, int _b) : a(_a), b(_b) {}
| ^~~~~~~~~~~~~~
test.cpp:9:3: note: candidate expects 2 arguments, 1 provided
test.cpp:5:8: note: candidate: ‘constexpr UnderlyingData::UnderlyingData(const UnderlyingData&)’
5 | struct UnderlyingData {
| ^~~~~~~~~~~~~~
test.cpp:5:8: note: no known conversion for argument 1 from ‘MyData<UnderlyingData>’ to ‘const UnderlyingData&’
test.cpp:5:8: note: candidate: ‘constexpr UnderlyingData::UnderlyingData(UnderlyingData&&)’
test.cpp:5:8: note: no known conversion for argument 1 from ‘MyData<UnderlyingData>’ to ‘UnderlyingData&&’
I've tried a number of permutations and can't seem to figure it out either. I don't understand why the constructor inferred seems to be UnderlyingData::UnderlyingData(MyData<UnderlyingData>)
as I'm just passing two numbers to it... Any advice I can get is much appreciated.
Same. I only effectively use one monitor but occasionally I want to plug my laptop to another monitor. It is frankly ridiculous that we have all these monitors with HDR, hidpi, VRR and high refresh rates. We also have technologies to daisy chain them. And Linux, Wayland or not, basically doesn't support any configuration other than 1080p 60hz sdr everywhere or a single monitor.
At this rate we will be lucky if we can get one of these things well supported in the next ten years. Sometimes, I wonder if technology development rate will accelerate fast enough such that it will reach escape velocity with respect to Linux display development speed. It already feels like we have regressed, and I wonder if it will get worse.