2013-03-15 50 views
0

我是新來的C++模板。我正在編寫一組可以操縱兩個不同模板類的函數。一個需要始終按值傳遞,另一個必須通過引用傳遞,因爲它代表了大量的數據。選擇c模板函數參數類型

這裏是一個簡化的例子。如果arg被標記爲ref類型,我希望函數簽名被定義爲由const ref引用它。

template<bool B, typename, typename T2> 
struct if_ {}; 

template<typename T1, typename T2> 
struct if_<true, T1, T2> { 
    typedef T1 type; 
}; 

template<typename T1, typename T2> 
struct if_<false, T1, T2> { 
    typedef T2 type; 
}; 

struct ByvalTypeTag {}; 
template<typename T> 
class Byval : public ByvalTypeTag 
{ 
    T somedata; 
}; 

struct ByrefTypeTag {}; 
template<typename T> 
class Byref : public ByrefTypeTag 
{ 
    T somedata; 
}; 

template<typename T> 
void myfunc(typename if_<std::is_base_of<ByrefTypeTag, T>::value, const T&, T>::type arg) 
{ 

} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Byref<int> arg; 
    myfunc(arg); 
    return 0; 
} 

我得到的錯誤是:

錯誤C2783: '無效MYFUNC(如果_ ::值,常量牛逼&,T> ::類型)':不能推導出模板參數的 'T'

也許這是錯誤的方式去做。如果可能的話,我試圖減少我爲相同功能編寫的相對重複模板的數量。

+0

編譯器將無法從參數'myfunc'推斷'T',表達過於複雜(並通過模板實例落後infering類型可能需要解決停機問題,在一般情況)。 ..你必須明確地提供類型爲'myfunc < Byref>(arg)'(或者有人可以找到其他一些棘手的方法來做你想做的事情,但這是最直接的解決方案) – 2013-03-15 23:30:01

回答

1

是的,編譯器無法推斷出類型。你需要爲它提供有T自己:

myfunc<ByRef<int>>(arg); 

另外,您可以使用更常用的標籤調度系統:

class byref 
{ 
    typedef byref_tag tag; 
    ... 
}; 

template < typename T > 
void fun(T const& t, byref_tag) { ... } 

template < typename T > 
void fun(T t, byval_tag) { ... } 

template < typename T > 
void fun(T const& t) 
{ 
    typedef typename T::tag tag; 
    fun(t,tag()); 
} 

另一種替代方案將涉及包裝函數和類模板。無論哪種方式,雖然外部功能必須通過參考。

1

您試圖從未推導的上下文中推導出類型T

在參數的依賴型的雙冒號的存在通常給你提示,你將不能夠推斷出參數的類型(除非你在同一個函數調用其他推導上下文的幫助,但在這裏你只有一個參數)。

從C++ 11標準第14.8.2.5/5:

非推導上下文是:

- 類型的嵌套名稱指定器,其是使用指定的一個合格的ID。

[...]

如果你需要一個具體的例子,this Q&A on StackOverflow提供了一個相當不錯的。在這種情況下,你可以明確地提供類型參數:

myfunc<Byref<int>>(arg); 

或者,你可以選擇在this second Q&A提出的兩個解決方法之一。

+0

因此,它聽起來像一個模板函數定義可以'檢測類型並在const&自動添加。我不希望用戶必須手動選擇模板。 – 2013-03-16 04:32:18

0

您可以使用此實現轉發參數。

template<typename T> 
void myfunc_impl(T arg) 
{ 
    // Do the work here. 
} 

template<typename T> 
void myfunc(const T &arg, typename std::enable_if<std::is_base_of<ByrefTypeTag, T>::value>::type* = 0) 
{ 
    myfunc_impl<const T&>(arg); // Pass a const ref 
} 

template<typename T> 
void myfunc(const T &arg, typename std::enable_if<std::is_base_of<ByvalTypeTag, T>::value>::type* = 0) 
{ 
    myfunc_impl<T>(arg);  // Pass a copy 
} 
+0

我有類似的東西,但我試圖去掉所有重複的代碼。對於任何一種類型的二元運算符函數,它最終都會要求所有的組合。有點醜,所以我希望有更清潔的東西。 – 2013-03-16 04:28:15