2017-01-16 53 views
3

我正在尝试构建一个混合模板,其基数都作为可变参数传递。我想通过将每个mixin类的构造函数参数作为参数传递给variadic模板构造函数来构造mixin当使用每个mixin类类型的对象调用时,variadic模板构造函数将编译。但是,如果我通过每个混合类的构造函数的参数(所有类只有一个参数的构造函数),它不会编译通过转发构造函数参数构建基于可变参数模板的mixin

我用gcc 7.0 -std = C++ 1Z

上午什么我做错了?

#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}; 
} 
+0

一个主要问题(无关你的问题虽然)是标准容器(和'std :: string')并不是真的被设计为继承自。他们没有虚拟析构函数。 –

+1

和编译器错误是...? – max66

+1

_“它不能编译”_继续... –

回答

2

的这里的问题是,std::initializer_list不能从转发参考推断。事实上,明确指定std::initializer_list使你的代码编译:

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

你可以找到更多信息有关std::initializer_list和演绎in this question


您可以通过创建一个帮手make_il功能强制std::initializer_list扣:

template <typename... Ts> 
auto make_il(Ts&&... xs) 
{ 
    return std::initializer_list<std::common_type_t<Ts...>>{ 
     std::forward<Ts>(xs)...}; 
} 

您的最终代码如下:

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