簡體   English   中英

具有參數數量的成員函數模板,具體取決於整數模板參數

[英]Member function template with the number of parameters depending on an integral template parameter

我有以下類模板:

template<class T, unsigned N>
class MyClass;

其中T是某種類型, N - 組件數。 可以使用MyClass{a1, a2, a3}初始化類MyClass{a1, a2, a3}其中參數的數量等於N

我想添加一個滿足以下要求的MyClass成員函數模板(讓我們命名為foo ):

  1. 它由另一個類型T2 template<class T2> void foo(..) (即template<class T2> void foo(..)
  2. 它接受足夠的數據來構造MyClass<T,N> ,但不能少於而不是更多。 違反此規則會導致編譯時錯誤。
  3. 它從參數的類型推導出T2 即我想要有可能調用foo({a1, a2, a3})foo(a1, a2, a3)或類似的東西,而不是每次都輸入<double>MyClass<double,N>

有沒有辦法實現這個功能,以滿足上述要求?

我已經考慮過和/或嘗試過以下解決方案:

1) 顯而易見的一個:

...
template<class T2>
void foo(MyClass<T2, N> arg);  
...
a.foo({1,2,3}); //compile-time error

原則上不能工作,因為支撐的初始化列表是非推導的上下文,因此它們不能推導出任何類型。 這很不幸,如果有效,我會很高興。

2) initializer_list

原則上不能工作,因為它無法在編譯時檢查參數的數量。

3) Variadic模板魔術

像下面的功能一樣整潔:

template<class...T2, class std::enable_if<sizeof...(T2) == N, int>::type = 0>
void foo(T2... args);
..
foo(1,2,3);

但是,我無法讓它工作 - T2仍然無法推斷。 也許有人知道為什么? 我使用了GCC4.7 20120121快照。

4) 丑陋的一個

基本上這與上面的相同,只是針對不同的N擴展到幾個重載。我最好重新實現MyClass作為不同N的一組特化,而不是使用這個。

template<class T2, class std::enable_if<N == 1, int>::type = 0>
void fun(T2 a1); //if N == 1
template<class T2, ..>
void fun(T2 a1, T2 a2); //if N == 2
template<class T2, ..>
void fun(T2 a1, T2 a2, T2 a3); //if N == 3
...

為什么不使用static_assert

template <typename T, size_t N>
class MyClass
{
public:
    template <typename... Args>
    void foo(Args&&... args)
    {
        static_assert(sizeof...(Args) == N, "Wrong number of arguments.");
        // Rest of the implementation.
    }
};

你的第三個變體的第二個非類型參數應該有前綴typename而不是class

template<class...T2, typename std::enable_if<sizeof...(T2) == N, int>::type = 0>
void foo(T2... args);
..
foo(1,2,3);

核實

Gcc 4.7.0快照有一些模板的錯誤我想,如果你用gcc 4.6.2 / 1嘗試它應該工作。

也許是這樣的:

#include <utility>
#include <type_traits>

template <typename T, unsigned int N>
class MyClass
{
    template <typename ...Args>
    typename std::enable_if<std::is_constructible<MyClass<T, N>, Args...>::value>::type
    foo(Args &&... args)
    {
        // for example:
        MyClass<T, N> m(std::forward<Args>(args)...);
        // ...
    }
};

這只有在MyClass有一個直接接受相關參數的構造函數(如MyClass(A1, A2, A3) )時才會起作用,但如果MyClass有一個需要初始化列表的構造函數,我覺得它不起作用,也不會起作用如果MyClass是需要大括號初始化的聚合。

也就是說,看起來你的MyClass 可能不會接受初始化列表,因為你說它必須精確地接受N參數,這是IL無法承諾的。

可能是,根據您的第三個變體,您可以從初始化列表中提取第一個參數並通過它推導出類型

template<class U, class...T2, class std::enable_if<sizeof...(T2) == N-1, int>::type = 0>
void foo(U u, T2... args)
{
    MyClass<U, N>({u, args...});
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM