簡體   English   中英

可變參數模板麻煩匹配const和非const std :: string

[英]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 && valuestd::string const & valuestd::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM