2017-01-16 27 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