I am trying to construct a mixin template whose bases are all passed as variadic template parameters. I would like to construct the mixin by passing the constructor parameters of each mixin class as a parameter to a variadic template constructor
The variadic template constructor when called with objects of each mixin class type compiles. But if I pass the constructor parameter of each mixin class (all the classes have a single parameter constructor), it doesn't compile
I am using gcc 7.0 with -std=c++1z
What am I doing wrong?
#include <vector>
#include <string>
#include <unordered_map>
#include <iostream>
template < typename... T >
struct Mixin : T...
{
Mixin() = delete;
Mixin(Mixin const &) = delete;
Mixin(Mixin &&) = delete;
template < typename... U >
Mixin(U &&... v) : T(std::forward < U >(v))...
{
}
};
int main()
{
using A = std::vector < std::string >;
using B = std::unordered_map < std::string, std::string >;
using C = std::string;
using M = Mixin < A, B, C >;
// This doesn't compile
M m1{{"hello", "world"}, { {"hello", "world" }, {"world", "hello"} }, "hello"};
// This compiles
A a({"hello", "world"}); B b({ {"hello", "world" }, {"world", "hello"} }); C c("hello");
M m2{a, b, c};
}
The problem here is that std::initializer_list cannot be deduced from a forwarding-reference. In fact, explicitly specifying std::initializer_list makes your code compile:
M m1{
std::initializer_list<std::string>{"hello", "world"},
std::initializer_list<std::pair<const std::string, std::string>>{{"hello", "world" },{"world", "hello"} },
"hello"};
wandbox example
You can find more information about std::initializer_list and deduction in this question.
You can force deduction of std::initializer_list by creating an helper make_il function:
template <typename... Ts>
auto make_il(Ts&&... xs)
{
return std::initializer_list<std::common_type_t<Ts...>>{
std::forward<Ts>(xs)...};
}
Your final code will look like:
using namespace std::literals::string_literals;
using kvp = std::pair<const std::string, std::string>;
M m1{
make_il("hello"s, "world"s),
make_il(kvp("hello"s, "world"s), kvp("world"s, "hello"s)),
"hello"};
wandbox example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With