![](/img/trans.png)
[英]c++ template member function that changes parameters depending on template parameter
[英]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
):
T2
template<class T2> void foo(..)
(即template<class T2> void foo(..)
) MyClass<T,N>
,但不能少於而不是更多。 違反此規則會導致編譯時錯誤。 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.