下面的代碼適用於gcc 4.7。這個想法是我有這些泛型函數,這些泛型函數在序列,指針,圖簇,對,用戶定義的類型以及其他類型上工作。如果其中一個函數是爲一個類型定義的,那麼全部都應該是。我遇到的問題是確定如何專門化他們。我決定定義一個專門用於每種類型的模板類,實現每個函數,然後定義一個自由函數,將其轉發給課堂實現。專門針對通用類型的功能組
#include <utility>
#include <vector>
#include <iterator>
#include <memory>
#include <iostream>
#include <algorithm>
using namespace std;
template< class M > struct Mon;
template< class X, class F,
class M = Mon< typename decay<X>::type > >
auto mon(X&& x, F f) -> decltype(M::mon(declval<X>(),f)) {
return M::mon(forward<X>(x), f);
}
template< class C > struct IsSeqImpl {
// Can only be supported on STL-like sequence types, not pointers.
template< class _C > static true_type f(typename _C::iterator*);
template< class _C > static false_type f(...);
typedef decltype(f<C>(0)) type;
};
template< class C > struct IsSeq : public IsSeqImpl<C>::type { };
/* Enable if is an STL-like sequence. */
template< class C, class R > struct ESeq : std::enable_if<IsSeq<C>::value,R> { };
template< class Seq >
struct Mon : ESeq< Seq, Seq >::type
{
template< class S, class F >
static S mon(const S& s, F f) {
S r;
transform(begin(s), end(s), back_inserter(r), f);
return r;
}
};
template< class P > struct IsPtrImpl {
template< class X > static true_type f(X);
template< class X > static false_type f(...);
typedef decltype(f(*declval<P>())) type;
};
template< class P > struct IsPtr : public IsPtrImpl<P>::type { };
template< class P, class R > struct EPtr : enable_if<IsPtr<P>::value,R> { };
template< class X > struct Mon< X* >
{
template< class F, class R = decltype(declval<F>()(declval<X>())) >
static unique_ptr<R> mon(X* x, F f) {
typedef unique_ptr<R> U;
return x ? U(new R(f(*x))) : U(nullptr);
}
};
int add_one(int x) { return x + 1; }
int main()
{
vector<int> v = {1,2,3,4,5};
int x = 5;
auto v2 = mon(v, add_one);
auto x2 = mon(&x, add_one);
// Should print 2 and 6.
cout << v2[0] << '\n';
cout << *x2 << '\n';
}
我希望做的是專門爲週一更通用的類型,但是當我再次嘗試使用enable_if繼承伎倆,GCC抱怨週一已定義。我也嘗試過使用第in this question號提到的第二個模板參數爲SFINAE的true_或false_type的技術,但沒有辦法讓它編譯。理想情況下,每當我想到一個類型的類型,我想定義一個動作,我應該能夠寫一個enable_if並寫在模板專業化的整個函數組。這節省了爲每個函數寫一個enable_if的麻煩。悲觀的是,我不得不爲每個類別中的每個似是而非的類型專門化組,以便真正成爲通用的。
我可以用通用和可擴展的方式寫這個嗎? PS:如果只有概念是C++的一部分11。
您認爲在類型的基類列表中使用'std :: enable_if'會怎樣? (我問,因爲我想確保我明白你想達到什麼。) –
你的意思是ESeq在Mon?由於Mon的所有函數都是靜態的,所以基礎對象永遠不會被構建。它只是防止非序列類型的實例化。雖然,如果我也不能爲其他類型也是完全沒有用的,所以我寫了Mon 而不是Mon 。 –
SplinterOfChaos