2017-09-21 169 views
0

我有一個類可以根據單個大小參數進行模板化。我想要一個構造函數,它接受基於模板大小參數的可變金額std::array。所以如果課堂模板化爲一個。它應該接受一個數組。如果模板兩個應該接受兩個等基於模板參數的模板類強制參數數

這是我想出了,但顯然它不工作:

template<std::size_t V> 
class Test 
{ 
public: 

    /* Constructors. */ 
    Test() {} 

    template <std::array<int, 3> ...Args, typename = typename std::enable_if<V == sizeof...(Args), void>::type> 
    Test(std::array<int, 3>&&... args) 
    { 

    } 

}; 


int main() 
{ 
    auto t = Test<1>({ 1, 2, 3 }); 
    auto t2 = Test<2>(
     { 1, 2, 3 }, 
     { 4, 5, 6 } 
    ); 
} 

我收到的錯誤是:

error C2993: 'std::array<int,3>': illegal type for non-type template parameter 'Args' 
note: see reference to class template instantiation 'Test<V>' being compiled 
error C3543: 'std::array<int,3> &&': does not contain a parameter pack 
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'Test<1>' 
note: No constructor could take the source type, or constructor overload resolution was ambiguous 
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'Test<2>' 
note: No constructor could take the source type, or constructor overload resolution was ambiguous 

任何幫助表示讚賞。

+0

如何移動'V = = ..的sizeof 。(Args)'方法裏面的'static_assert'?實際上它應該是'template ',你還需要檢查每個參數的類型。 – VTT

+0

@VTT我得到幾乎相同的錯誤。我已經在問題中發佈了它! –

+0

@VTT函數內部的'static_assert'比正確的模板元編程會產生一個錯誤,所以如果存在多個構造函數,可能會導致一些問題(例如)選擇了無效的重載。 –

回答

1

有了繼承,你可以這樣做:

template <std::size_t, typename T> using alwaysT = T; 

template <typename T, typename Seq> struct TestHelper; 

template <typename T, std::size_t ... Is> 
struct TestHelper<T, std::index_sequence<Is...>> 
{ 
    TestHelper(alwaysT<Is, T>... arr) {} 
}; 

template<std::size_t V> 
class Test : TestHelper<const std::array<int, 3>&, std::make_index_sequence<V>> 
{ 
public: 
    using TestHelper<const std::array<int, 3>&, std::make_index_sequence<V>>::TestHelper; 
    Test() = default; 
}; 

Demo

+0

你能概括這個多維度和自定義類型嗎?現在3是硬編碼的,類型是int。也可以參數化這些呢?我知道這超出了問題的範圍,但我很好奇。 –

+0

已更新答案以允許更多自定義。由您來適應您的需求。 – Jarod42

1

一些工作從評論的解決方案:

#include <type_traits> 
#include <array> 

template<typename... TArgs> struct 
contains_only_array_of_3_int 
{ 
    static constexpr bool const value{false}; 
}; 

template<typename TBack> struct 
contains_only_array_of_3_int<TBack> 
{ 
    static constexpr bool const value 
    { 
     ::std::is_same<::std::array<int, 3>, TBack>::value 
    }; 
}; 

template<typename TFront, typename... TRest> struct 
contains_only_array_of_3_int<TFront, TRest...> 
{ 
    static constexpr bool const value 
    { 
     contains_only_array_of_3_int<TFront>::value 
     && 
     contains_only_array_of_3_int<TRest...>::value 
    }; 
}; 

template<std::size_t V> class 
Test 
{ 
    public: 
    Test() {} 

    template <typename... TArgs> 
    Test(TArgs && ... args) 
    { 
     static_assert 
     (
      sizeof...(TArgs) == V 
     , "arguments count mismatch" 
     ); 
     static_assert 
     (
      contains_only_array_of_3_int<::std::decay_t<TArgs>...>::value 
     , "arguments type mismatch" 
     ); 
    } 
}; 

int main() 
{ 
    Test<1> t 
    { 
     ::std::array<int, 3>{ 1, 2, 3 } 
    }; 
    Test<2> t2 
    { 
     ::std::array<int, 3>{ 1, 2, 3 } 
    , ::std::array<int, 3>{ 4, 5, 6 } 
    }; 
    Test<3> t3 
    { 
     ::std::array<int, 3>{ 1, 2, 3 } 
    , ::std::array<int, 3>{ 4, 5, 6 } 
    , ::std::array<int, 3>{ 7, 8, 9 } 
    }; 
    Test<3> t3_args_count_fail 
    { 
     ::std::array<int, 3>{ 1, 2, 3 } 
    , ::std::array<int, 3>{ 4, 5, 6 } 
    }; 
    Test<3> t3_args_tupe_fail 
    { 
     ::std::array<int, 3>{ 1, 2, 3 } 
    , ::std::array<int, 2>{ 4, 5 } 
    , ::std::array<int, 3>{ 7, 8, 9 } 
    }; 
    return(0); 
} 

online editor

+0

當您使用轉發參考時,缺少'std :: decay_t'。 – Jarod42

+0

'contains_only_array_of_3_int'也可以簡化,請參見[Demo](https://ideone.com/8ikS42) – Jarod42

+0

我會使用['is_convertible'](http://en.cppreference.com/w/cpp/types/is_convertible)而不是'is_same';否則,你將失去使用不是'array '的東西來調用它的能力,但可以隱式轉換爲一個。否則,這將不會像您以某種方式手動編寫函數來獲取正確的參數數量一樣。 –