[英]Variadic template trouble matching const and non-const std::string
我在構建可變參數模板時遇到了麻煩,其中擴展功能正確地匹配了非const和const std::string
。 我有一個通用的匹配函數,在某些情況下會被調用。
我將代碼簡化為以下示例。 不是字符串的東西應該以通用函數結束。 作為字符串的事物應該結束於第二個函數,該函數另外輸出“ STRING”。
#include <iostream>
#include <string>
template<typename X, typename T>
void extend_exception( X & ex, T&& value )
{
ex << value << std::endl;
}
template<typename X>
void extend_exception( X & ex, std::string && value )
{
ex << "STRING: " << value << std::endl;
}
template<typename X, typename TF, typename ... TR>
void extend_exception( X & ex, TF&& f, TR&& ... rest )
{
extend_exception( ex, std::forward<TF>(f) );
extend_exception( ex, std::forward<TR>(rest)... );
}
int main()
{
extend_exception( std::cout, std::string( "Happy" ) );
std::string var( "var" );
extend_exception( std::cout, var );
extend_exception( std::cout, var, std::string( "Combo" ), const_cast<std::string const&>(var));
return 0;
}
在以上版本中,兩個var
使用不會傳遞給字符串函數。 我嘗試了其他各種方法來指定參數,但似乎沒有辦法: std::string && value
, std::string const & value
, std::string const && value
。 我也確實嘗試過std::string & value
,然后非常量字符串匹配,而不是const字符串。 通過具有兩個不同的功能,這至少為我提供了一種解決方法,但是我懷疑我不需要這樣做。
如何在此處編寫一個將為const,non-const和臨時字符串對象調用的函數?
我正在使用g ++ 4.6.3
這非常棘手, T&&
是所謂的通用引用,而std::string&&
則不是(不涉及類型推導)。 請參閱此處以獲得良好的解釋。 解決方法:
template<typename X, typename T>
void extend_exception_( X & ex, T&& value, ... )
{
ex << value << std::endl;
}
template<typename X, typename T,
typename = typename std::enable_if<
std::is_same<std::string, typename std::decay<T>::type>::value>::type>
void extend_exception_( X & ex, T && value, int )
{
ex << "STRING: " << value << std::endl;
}
template <typename T> using identity = T;
template<typename X, typename ... R>
void extend_exception( X & ex, R&& ... rest )
{
identity<bool[]>{false,(extend_exception_(ex, std::forward<R>(rest), 0), false)...};
}
int main()
{
extend_exception( std::cout, std::string( "Happy" ) );
std::string var( "var" );
extend_exception( std::cout, var );
extend_exception( std::cout, var, std::string( "Combo" ) );
}
您不能將非右值綁定到右值引用,因此string&&
不起作用,但const std::string&
可用於var
。 但是, var
不是const,因此實現重載的最短路徑是將T&&
折疊為std::string&
並采用第一個。
您需要找出相互排斥的類型,或使用SFINAE編寫兩個在正確的參數類型上互斥的類型。
這是因為您的字符串版本僅捕獲作為右值傳遞的字符串。 左值將傳遞給泛型函數。 如果T是模板參數而U不是(這是U是某種指定類型),則T &&和string &&之間,或更一般的T &&和U &&之間存在巨大差異。 參見Scott Meyers關於通用參考文獻的注釋
為了使函數按需要工作,您需要做的是添加另一個重載:
template<typename X>
void extend_exception( X & ex, std::string const& value )
{
ex << "STRING: " << value << std::endl;
}
我重新討論了這個問題,並提出了一個涉及使用類標記的解決方案。 我寫了一篇完整的解決方案/討論文章 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.