I tried to create vector of properties. This vector supposed to be kind of "mark" that would help distinguish between other tuples.
This simple snippet works on clang 6.0 and does not work on any of GCC versions (tried only 7.3.0, 8.1.0):
#include <tuple>
#include <string>
using namespace std;
template <class... Ts>
struct vector {
using tuple_type = std::tuple<Ts...>;
tuple_type properties;
template <class... Ps>
vector(Ps&&... ps)
: properties(std::forward<Ps>(ps)...)
{}
};
template <class... Ps> vector(Ps&&... ps) -> vector<Ps...>;
int main() {
vector v{ std::string("heh"), int(7) };
}
GCC 8.1.0 throws:
./template_argument_deduction_for_class_templates.cpp: In instantiation of ‘vector<Ts>::vector(Ps&& ...) [with Ps = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int}; Ts = {}]’:
./template_argument_deduction_for_class_templates.cpp:22:39: required from here
./template_argument_deduction_for_class_templates.cpp:15:38: error: no matching function for call to ‘std::tuple<>::tuple(std::__cxx11::basic_string<char>, int)’
: properties(std::forward<Ps>(ps)...)
^
In file included from ./template_argument_deduction_for_class_templates.cpp:2:
/usr/include/c++/8.1.0/tuple:901:2: note: candidate: ‘template<class _Alloc> std::tuple<>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<>&)’
tuple(allocator_arg_t, const _Alloc&, const tuple&) { }
^~~~~
/usr/include/c++/8.1.0/tuple:901:2: note: template argument deduction/substitution failed:
./template_argument_deduction_for_class_templates.cpp:15:38: note: candidate expects 3 arguments, 2 provided
: properties(std::forward<Ps>(ps)...)
^
In file included from ./template_argument_deduction_for_class_templates.cpp:2:
/usr/include/c++/8.1.0/tuple:899:2: note: candidate: ‘template<class _Alloc> std::tuple<>::tuple(std::allocator_arg_t, const _Alloc&)’
tuple(allocator_arg_t, const _Alloc&) { }
^~~~~
/usr/include/c++/8.1.0/tuple:899:2: note: template argument deduction/substitution failed:
./template_argument_deduction_for_class_templates.cpp:15:38: note: cannot convert ‘std::forward<std::__cxx11::basic_string<char> >((* & ps#0))’ (type ‘std::__cxx11::basic_string<char>’) to type ‘std::allocator_arg_t’
: properties(std::forward<Ps>(ps)...)
^
In file included from ./template_argument_deduction_for_class_templates.cpp:2:
/usr/include/c++/8.1.0/tuple:896:7: note: candidate: ‘constexpr std::tuple<>::tuple()’
tuple() = default;
^~~~~
/usr/include/c++/8.1.0/tuple:896:7: note: candidate expects 0 arguments, 2 provided
/usr/include/c++/8.1.0/tuple:890:11: note: candidate: ‘constexpr std::tuple<>::tuple(const std::tuple<>&)’
class tuple<>
^~~~~~~
/usr/include/c++/8.1.0/tuple:890:11: note: candidate expects 1 argument, 2 provided
/usr/include/c++/8.1.0/tuple:890:11: note: candidate: ‘constexpr std::tuple<>::tuple(std::tuple<>&&)’
/usr/include/c++/8.1.0/tuple:890:11: note: candidate expects 1 argument, 2 provided
Why does GCC deduces that Ts is empty pack? Did I made some mistake here or is it compiler problem?
According to this link http://en.cppreference.com/w/cpp/compiler_support GCC should support this feature.