#include <utility>
#include <iostream>
struct Data {
uint8_t m_x;
double m_y;
uint32_t m_z;
Data(uint8_t x, double y, uint32_t z) : m_x(x), m_y(y), m_z(z) {
std::cout << "constructor called" << std::endl;
}
};
template <class Data, typename... Args>
class Layer1 {
public:
void foo(Args&&... args) {
Data(std::forward(args)...);
}
};
int main() {
Layer1<Data, uint8_t, double, uint32_t> layer1;
layer1.foo(1, 1.1, 2);
}
When I compile the code above, gcc 8.2 outputs:
$ g++ -Wall test_forward.cpp -o test_forward -O3 -std=c++17
test_forward.cpp: In instantiation of ‘void Layer1<Data, Args>::foo(Args&& ...) [with Data = Data; Args = {unsigned char, double, unsigned int}]’:
test_forward.cpp:39:22: required from here
test_forward.cpp:31:16: warning: unused variable ‘layer2’ [-Wunused-variable]
Layer2<Data> layer2;
^~~~~~
[hchan@heilinux cpp]$ g++ -Wall test_forward.cpp -o test_forward -O3 -std=c++17
[hchan@heilinux cpp]$ g++ -Wall test_forward.cpp -o test_forward -O3 -std=c++17
test_forward.cpp: In instantiation of ‘Layer1<Data, Args>::MyData::MyData(Args&& ...) [with Data = Data; Args = {unsigned char, double, unsigned int}]’:
test_forward.cpp:32:3: required from ‘void Layer1<Data, Args>::foo(Args&& ...) [with Data = Data; Args = {unsigned char, double, unsigned int}]’
test_forward.cpp:39:22: required from here
test_forward.cpp:27:51: error: no matching function for call to ‘forward(unsigned char&)’
MyData(Args&&... args) : i(0), data(std::forward(args)...) {}
~~~~~~~~~~~~^~~~~~
In file included from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/stl_pair.h:59,
from /opt/rh/devtoolset-8/root/usr/include/c++/8/utility:70,
from test_forward.cpp:1:
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:74:5: note: candidate: ‘template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&)’
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
^~~~~~~
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:74:5: note: template argument deduction/substitution failed:
test_forward.cpp:27:51: note: couldn't deduce template parameter ‘_Tp’
MyData(Args&&... args) : i(0), data(std::forward(args)...) {}
~~~~~~~~~~~~^~~~~~
In file included from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/stl_pair.h:59,
from /opt/rh/devtoolset-8/root/usr/include/c++/8/utility:70,
from test_forward.cpp:1:
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:85:5: note: candidate: ‘template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&&)’
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
^~~~~~~
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:85:5: note: template argument deduction/substitution failed:
test_forward.cpp:27:51: note: couldn't deduce template parameter ‘_Tp’
MyData(Args&&... args) : i(0), data(std::forward(args)...) {}
~~~~~~~~~~~~^~~~~~
[hchan@heilinux cpp]$ g++ -Wall test_forward.cpp -o test_forward -O3 -std=c++17
[hchan@heilinux cpp]$
[hchan@heilinux cpp]$
[hchan@heilinux cpp]$
[hchan@heilinux cpp]$ g++ -Wall test_forward.cpp -o test_forward -O3 -std=c++17
test_forward.cpp: In instantiation of ‘void Layer1<Data, Args>::foo(Args&& ...) [with Data = Data; Args = {unsigned char, double, unsigned int}]’:
test_forward.cpp:23:22: required from here
test_forward.cpp:17:20: error: no matching function for call to ‘forward(unsigned char&)’
Data(std::forward(args)...);
~~~~~~~~~~~~^~~~~~
In file included from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/stl_pair.h:59,
from /opt/rh/devtoolset-8/root/usr/include/c++/8/utility:70,
from test_forward.cpp:1:
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:74:5: note: candidate: ‘template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&)’
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
^~~~~~~
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:74:5: note: template argument deduction/substitution failed:
test_forward.cpp:17:20: note: couldn't deduce template parameter ‘_Tp’
Data(std::forward(args)...);
~~~~~~~~~~~~^~~~~~
In file included from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/stl_pair.h:59,
from /opt/rh/devtoolset-8/root/usr/include/c++/8/utility:70,
from test_forward.cpp:1:
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:85:5: note: candidate: ‘template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&&)’
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
^~~~~~~
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/move.h:85:5: note: template argument deduction/substitution failed:
test_forward.cpp:17:20: note: couldn't deduce template parameter ‘_Tp’
Data(std::forward(args)...);
~~~~~~~~~~~~^~~~~~
For some reason, it seems like the template deduction fails. If I change Data(std::forward(args)...)
to Data(std::forward<Args>(args)...)
, it works.
I wonder why compiler fails to deduce the argument types and what compiler is actually thinking of the type (i.e. no matching function for call to ‘forward(unsigned char&)’
).
Basically, I am trying understand why more hint is needed (i.e. explicitly states <Args>
).
Thanks!