2010-10-07 23 views
0

模板參數的數目我有這樣定義的方法和兩類:減少爲

template<template<class X> class T> 
void doSomething() 
{ 
    T<int> x; 
} 
template <class T> 
class ClassWithOneArg 
{ 
    T t; 
}; 

template <class T1, class T2> 
class ClassWithTwoArgs 
{ 
    T1 t1; 
    T2 t2; 
}; 

我現在可以

doSomething<ClassWithOneArg>(); 

,但我不能

doSomething<ClassWithTwoArgs>(); 

然而,我想通過ClassWithTwoArgs做一些事情,其中​​T2 = double。

我發現的唯一的方法是創建

template <class T1> 
class ClassWithTwoArgs_Child 
    : public ClassWithTwoArgs<T1, double> 
{ 
}; 

然後

doSomething<ClassWithTwoArgs_Child>(); 

這工作,但在我的具體情況下,所有類需要一個構造函數的參數,因此我要創建一個構造函數在_Child-class中也有這個參數,並將其傳遞給我真正想避免的基礎。

你有一個想法該怎麼做?

非常感謝!

回答

3

間接是一種解決方案。取而代之的是模板的模板參數傳遞一個「元功能」 - 即一個類型映射到另一個與嵌套類模板結構形式的功能:

struct mf1 { 
    template<class Arg1> 
    struct eval { 
    typedef ClassTemplateWithOneArg<Arg1> type; 
    }; 
}; 

template<class Arg2> 
struct mf2 { 
    template<class Arg1> 
    struct eval { 
    typedef ClassTemplateWithTwoArgs<Arg1,Arg2> type; 
    }; 
}; 

template<class MetaFunc> 
void do_something() 
{ 
    typedef typename MetaFunc::template eval<int>::type clazztype; 
    clazztype x; 
} 

void foo() { 
    do_something<mf1>(); 
    do_something<mf2<double> >(); 
} 

在C++ 0x中這樣就可以減少一個「模板類型定義」:

template<class Arg1> 
using NewClassTemplate = ClassTemplateWithTwoArgs<Arg1,double>; 

,它允許你通過NewClassTemplate爲模板,模板參數也只接受一個模板參數。

+0

請注意來自菲利普的評論(恐怕這不是我正在尋找的,因爲可能有其他情況下,我也想通過「ClassWithTwoArgs 」。)。這個解決方案不會工作,因爲'double'是硬編碼 – Chubsdad 2010-10-07 13:58:11

+0

@chubsdad,當然,您可以參數化元函數。看看我如何將mf2轉換成模板本身以及如何使用它。 – sellibitze 2010-10-07 14:17:56

+0

謝謝,這解決了我的問題!改變「doSomething」不是問題,但我不想在「doSomething」之外定義Template-Argument(在我的例子中爲「int」)。 – Philipp 2010-10-08 11:13:53

0

這適用於MSVC:

template<class T> 
void doSomething() 
{ 
    T x; 
} 

// class definitions omitted... 

void test() { 
    doSomething<ClassWithOneArg<int> >(); 
    doSomething<ClassWIthTwoArgs<int, double> >(); 
} 

我不完全理解你爲什麼要定義模板的模板參數的第一個參數是intdoSomething內。看起來像「模板氣味」給我,因爲doSomething必須知道很多關於它的模板模板參數。

以我提出的方式撥打doSomething會不會更乾淨? (但顯然我不知道你的電話的上下文)。

+0

恐怕這不是我正在尋找的,因爲可能還有其他情況下我還想通過「ClassWithTwoArgs 」。 – Philipp 2010-10-07 12:43:58

+0

你想在'doSomething'裏面第一個參數總是int,但是第二個參數在調用'doSomething'時應該被定義? – WolfgangA 2010-10-07 12:49:13

+0

請注意,我編輯了我的答案 – WolfgangA 2010-10-07 12:49:31

1

沒有通用的解決方案。你最好的選擇是

template<class T> 
void doSomething() 
{ 
    T x; 
} 
template <class T> 
class ClassWithOneArg 
{ 
    T t; 
}; 

template <class T1, class T2 = double> 
class ClassWithTwoArgs 
{ 
    T1 t1; 
    T2 t2; 
}; 

int main(){ 
    doSomething<ClassWithOneArg<int>>(); 
    doSomething<ClassWithTwoArgs<int, double> >(); 
} 
1

看來你以後有什麼類似於分配器的重新綁定(給定的分配器,容器需要能夠產生針對不同類型的分配器 - 例如std::list<int>可能需要從allocator<int>一個allocator<list_node<int> >

。但是,類模板將不得不爲此修改。

template<class T> 
void doSomething(const T&) 
{ 
    typename T::template rebind_1st<int>::type x; 
} 

template <class T> 
class ClassWithOneArg 
{ 
    T t; 
public: 
    template <class U> 
    struct rebind_1st { typedef ClassWithOneArg<U> type; }; 
}; 

template <class T1, class T2> 
class ClassWithTwoArgs 
{ 
    T1 t1; 
    T2 t2; 
public: 
    template <class U> 
    struct rebind_1st { typedef ClassWithTwoArgs<U, T2> type; }; 
}; 

int main() 
{ 
    doSomething(ClassWithOneArg<char>()); 
    doSomething(ClassWithTwoArgs<char, double>()); 
} 
1

假設你想用一個不同類型的第一個模板參數聲明相同類的模板實例,它會出現一個版本的訪問者的代碼可能不需要修改原來的類。

template <class T, class NewFirstArg> 
struct rebind_1st; 

template <template <class> class T, class Arg1, class NewFirstArg> 
struct rebind_1st<T<Arg1>, NewFirstArg> 
{ 
    typedef T<NewFirstArg> type; 
}; 

template <template <class, class> class T, class Arg1, class Arg2, class NewFirstArg> 
struct rebind_1st<T<Arg1, Arg2>, NewFirstArg> 
{ 
    typedef T<NewFirstArg, Arg2> type; 
}; 

template <class T> 
void foo() 
{ 
    typename rebind_1st<T, int>::type x; 
    (void)x; 
} 

template <class T> 
struct One{}; 

template <class T1, class T2> 
struct Two{}; 

int main() 
{ 
    foo<One<char> >(); 
    foo<Two<char, double> >(); 
}