c++ - 在模板化之前使用隐式转换

标签 c++ template-specialization overload-resolution

我尝试结合使用模板特化和隐式转换,将模板类型分为 3 类:

  1. 可以隐式转换为字符串的类型
  2. 可以隐式转换为 double 的类型
  3. 无法隐式转换为字符串或 double 类型的类型

然而,在我的这次尝试中,所有可以转换为 double 型或字符串的类型最终都以类型 T 的默认情况结束。

template<>
void Foo(std::string s)
{
    //can be converted to a string
}

template<>
void Foo(double d)
{
    //can be converted to a double
}

template<typename T>
void Foo(T t)
{
    //cannot be converted to a string or a double 
}

struct Other {};

int main()
{
    Foo("bar");// creates Foo(const char*) instead of converting to string
    Foo(1);// creates Foo(int) instead of converting to double
    Other o
    Foo(o);// creates Foo(Other)
}

另一方面,如果删除模板,隐式转换就会起作用,但代价是无法处理“任一”类型。

void Foo(std::string s)
{
    //can be converted to a string
}

void Foo(double d)
{
    //can be converted to a double
}

struct Other {};

int main()
{
    Foo("bar");// const char* -> std::string
    Foo(1);// int -> double
    Other o
    Foo(o);// No overload available for this type
}

在创建新的模板化函数之前,有没有办法优先考虑对现有专用模板的隐式转换?或者也许我应该采用完全不同的方式来解决这个问题?

最佳答案

不要专门化...老实说,如果解决方案 Y 存在问题 X,那么专门化函数模板几乎总是 Z。对于要调用的专门化,推导的模板参数必须完全正确 em> 我们正在专门研究的那些。此外,在重载决策中甚至不考虑特化是否存在!重载仅通过主模板声明来解决。

对于您的问题,您需要重载,以便在重载决策中始终考虑这两种自定义情况。然后,您只需确保在需要时简单地丢弃常规 catch-call 函数即可。 SFINAE 以及一些标准类型特征将完全实现这一点。

#include <type_traits>

// Overloads. Not templates!

void Foo(std::string s)
{
    //can be converted to a string
}


void Foo(double d)
{
    //can be converted to a double
}

template<typename T>
std::enable_if_t<!(std::is_convertible_v<T, std::string> || std::is_convertible_v<T, double>)>
Foo(T t)
{
    //cannot be converted to a string or a double 
}

看看这个条件是否正是您想要检查的?类型特征验证是否可以进行转换,在这种情况下 std::enable_if_t是一种格式错误的类型(不存在)。因此,过载被简单地丢弃(因为S替代F失败IN而不是A

如果两种转换都不可能,则不会丢弃模板重载,并且 std::enable_if_t - 函数的返回类型 - 为 void(voidenable_if_t 默认解析的类型)。


如果您可以使用支持最新 C++ 标准的较新编译器,您甚至可以以比经典 SFINAE 更用户友好的方式编写它

#include <concepts>

template<typename T>
    requires !(std::convertible_to<T, std::string> || std::convertible_to<T, double>)
void Foo(T t)
{
    //cannot be converted to a string or a double 
}

约束现在可以在声明中占据自己的位置,而无需返回类型。

关于c++ - 在模板化之前使用隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69782694/

相关文章:

c++ - 如何使用自定义非纯交换函数参数化算法?

c++ - _GLIBCXX_USE_NANOSLEEP 到底是什么?

c++ - 引用 const 的模板特化

c++ - 如何在编译时获得多维 std::vector 的深度?

c++ - 特化非模板类的成员函数模板

c++ - 部分模板特化数组使用

casting - 当存在不同的重载时强制向上转型

c++ - SFINAE 离开了一个拷贝构造函数

c++ - 为什么当使用 _ITERATOR_DEBUG_LEVEL=0 销毁 vector 时,Visual C++ 2010 仍调用 Orphan_all?

c++ - std::vector::size 返回一个 int 类型或 unsigned int