繁体   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