使用“std::enable_if_t”“函数模板已被定义”[重复]

2024-03-13

我正在尝试使用std::enable_if_t根据传递给模板函数的类型特征来切换模板函数的实现。

这是一个例子:

#include <iostream>
#include <type_traits>

// Enable if "T" is integral
template <typename T,
    typename = std::enable_if_t<std::is_integral_v<T>>
>
void print(T value)
{
    std::cout << "Integral: " << value << std::endl;
}

// Enable if "T" is not integral
template <typename T,
    typename = std::enable_if_t<!std::is_integral_v<T>>
>
void print(T value)
{
    std::cout << "Not Integral: " << value << std::endl;
}

int main()
{
    int i = 42;
    print(i);

    double d = 42.0;
    print(d);
}

问题是,这无法编译,说明:

'void print(T)':函数模板已被定义。

这对我来说感觉很奇怪,因为std::is_integral_v<T> and !std::is_integral_v<T>永远不会同时评估为 true,因此每当启用一个实现时,就应禁用另一个实现。

为什么这不起作用?解决此问题并获得我正在寻找的功能的最佳方法是什么?


CPP参考 https://en.cppreference.com/w/cpp/types/enable_if:

一个常见的错误是声明两个仅不同的函数模板 在他们的默认模板参数中。这不起作用,因为 声明被视为同一函数的重新声明 模板(函数中不考虑默认模板参数 模板等价)。

/*** WRONG ***/

struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              typename = std::enable_if_t<std::is_integral<Integer>::value>
    >
    T(Integer) : m_type(int_t) {}

    template <typename Floating,
              typename = std::enable_if_t<std::is_floating_point<Floating>::value>
    >
    T(Floating) : m_type(float_t) {} // error: treated as redefinition
};

/* RIGHT */

struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              std::enable_if_t<std::is_integral<Integer>::value, int> = 0
    >
    T(Integer) : m_type(int_t) {}

    template <typename Floating,
              std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
    >
    T(Floating) : m_type(float_t) {} // OK
};

在模板类型中使用enable_if时应小心 命名空间范围函数模板的非类型参数。一些 ABI 像 Itanium ABI 这样的规范不包括 非类型模板参数的实例化相关部分 mangling,意味着两个不同函数的专业化 模板可能最终会出现相同的错误名称并且出现错误 链接在一起。例如:

// first translation unit

struct X {
    enum { value1 = true, value2 = true };
};

template<class T, std::enable_if_t<T::value1, int> = 0>
void func() {} // #1

template void func<X>(); // #2

// second translation unit

struct X {
    enum { value1 = true, value2 = true };
};

template<class T, std::enable_if_t<T::value2, int> = 0>
void func() {} // #3

template void func<X>(); //#4

函数模板 #1 和 #3 具有不同的签名,并且是 独特的模板。尽管如此,#2和#4,尽管是 不同函数模板的实例化,具有相同的损坏 Itanium C++ ABI 中的名称 (_Z4funcI1XLi0EEvv),表示 链接器会错误地认为它们是同一实体。

Fix:

#include <iostream>
#include <type_traits>

// Enable if "T" is integral
template <typename T,
    std::enable_if_t<std::is_integral_v<T>, int> = 0
>
void print(T value)
{
    std::cout << "Integral: " << value << std::endl;
}

// Enable if "T" is not integral
template <typename T,
    std::enable_if_t<!std::is_integral_v<T>, int> = 0
>
void print(T value)
{
    std::cout << "Not Integral: " << value << std::endl;
}

int main()
{
    int i = 42;
    print(i);

    double d = 42.0;
    print(d);
}

更好的是,使用概念:

#include <iostream>
#include <concepts>

// Enable if "T" is integral
template <std::integral T>
void print(T value)
{
    std::cout << "Integral: " << value << std::endl;
}

// Enable if "T" is not integral
template <typename T>
void print(T value)
{
    std::cout << "Not Integral: " << value << std::endl;
}

int main()
{
    int i = 42;
    print(i);

    double d = 42.0;
    print(d);
}

LIVE https://gcc.godbolt.org/z/X8NRZb

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用“std::enable_if_t”“函数模板已被定义”[重复] 的相关文章

  • 为什么在从同一解决方案引用另一个项目时会出现 FileNotFound 异常?

    我正在学习如何使用 NUnit 我的解决方案中有我的主项目 并在同一解决方案中创建了一个单独的项目 该项目将保存我的单元测试 并具有自己的命名空间 从该项目中 我添加对主项目的引用并添加 using MainProjectNamespace
  • 有没有办法将所有内容都包含在 dbcontext 中?

    当查询一个DbContext急切加载时 需要Include Navigation 为了填充导航属性 然而 在某些情况下 我想简单地Include all实体的导航属性 有没有办法做到这一点 或者有办法做到这一点 我假设你可以反思 但我宁愿避
  • fork 和 exec 之间的区别

    两者有什么区别fork and exec 指某东西的用途fork and exec它体现了 UNIX 的精神 它提供了一种非常简单的方法来启动新进程 The fork调用基本上复制了当前进程 在almost任何方式 并非所有内容都会被复制
  • C++ 标准是否允许未初始化的 bool 导致程序崩溃?

    我知道一个 未定义的行为 C 几乎可以让编译器做任何它想做的事情 然而 我遇到了一次令我惊讶的崩溃 因为我认为代码足够安全 在这种情况下 真正的问题仅发生在使用特定编译器的特定平台上 并且仅在启用优化的情况下发生 我尝试了几种方法来重现问题
  • C++ 天花板函数的奇怪结果

    我一直在尝试天花板功能并得到一些奇怪的结果 如果我对十进制数乘以百执行 ceil 运算 我会得到一定的结果 但是 如果我直接对该乘法的结果执行 ceil 我会得到完全不同的输出 另一个问题是 这些不同的结果仅发生在某些数字上 任何帮助 将不
  • Web 应用程序框架:C++ 与 Python

    作为一名程序员 我熟悉 Python 和 C 我正在考虑编写自己的简单 Web 应用程序 并且想知道哪种语言更适合服务器端 Web 开发 我正在寻找一些东西 它必须是直观的 我认识到 Wt 存在并且它遵循 Qt 的模型 我讨厌 Qt 的一件
  • 委托和接口如何互换使用?

    我可以使用接口方法代替委托吗 如何 我发现搜索接口方法比使用委托更快 我希望有一个简单的代码片段 理论上 可以通过包含单个方法的接口 例如 Java 没有委托 来完成委托完成的所有工作 然而 它使代码变得更加冗长并且没有带来什么好处 话又说
  • 运行 C# exe 文件

    复制 为什么我的 NET 应用程序在从网络驱动器运行时会崩溃 https stackoverflow com questions 148879 why does my net application crash when run from
  • 如何获取 C# PriorityQueue 元素的优先级

    我正在初始化一个存储 XY 坐标的优先级队列 根据距原点的欧几里得距离确定优先级 我创建了一个自定义Comparer这使得它作为最大堆运行 PriorityQueue
  • 如何使用 DesignData 帮助开发 Metro 应用程序?

    我一直在 Windows Phone 应用程序中愉快地使用 DesignData 我希望使用它来帮助在 VS2012 Blend for VS 中的 Metro 风格应用程序中可视化设计 我已经尝试过希望显而易见的方法
  • 有没有办法关闭 Hangfire 使用 Serilog 进行的日志记录?

    有没有办法关闭 Hangfire 使用 Serilog 进行的日志记录 我们正在使用我们自己的抽象 我不希望在使用 Serilog 时来自 Hangfire 记录器的所有额外噪音 INIT call under web project na
  • 泛型类上的 DebuggerDisplay

    我在应用时遇到问题DebuggerDisplay泛型类的属性 DebuggerDisplay foo class Foo DebuggerDisplay Bar t class Bar
  • C++ 为非虚方法指定初始化

    我有 a h 如下所示 class A public void doSomething 0 然后我有 b h 如下所示 include a h class b public A public void doSomething 我只是想通过尝
  • 模板“内联”函数的静态局部变量[重复]

    这个问题在这里已经有答案了 static的局部变量inline如果我的理解是正确的 C 中的函数保证像单个全局变量一样存在 如果inline函数是一个模板 编译器可以在哪里生成该函数的多个版本 下面这篇文章应该很好地回答你的问题 http
  • C++ fill() 与 uninitialized_fill()

    您好 我是初学者 我想知道容器的 fill 和 uninitialized fill 之间的区别 我在谷歌上进行了快速搜索 但没有得到很好的答案 有人可以帮助我吗 fill 将值 使用赋值运算符 分配给已构造的对象 uninitialize
  • 阻止用户取消选择列表框中的项目?

    我有一个列表框 里面有很多项目 用户可以单击某个项目来编辑其内容 如何防止用户取消选择所有项目 即 用户不应该无法选择任何内容 您的情况缺少一个案例 即清除列表后 您将选择列表中不再存在的项目 我通过添加额外的检查来解决这个问题 var l
  • C++20 views::join 在生成的嵌套范围::single_view 上进入无限循环

    我正在使用 GCC 实现 v10 2 和 v11 来处理 C 20 范围 测试的行为std views join https en cppreference com w cpp ranges join view 我尝试使用生成嵌套视图sin
  • 通过 MVC 将数据写入数据库的最佳方法是什么?

    我正在使用 MVC 和 EF Core 开发一个家庭作业项目 我正在寻找将数据写入数据库的最佳方法 我是初学者 有两张桌子 Predbilje ba 报名 和Seminari 研讨会 public class Predbilje ba Ke
  • 为什么 C++ 元组如此奇怪?

    我通常创建自定义structs将不同类型的值分组在一起时 这通常很好 而且我个人发现命名成员访问更容易阅读 但我想创建一个更通用的 API 在其他语言中广泛使用元组后 我想返回类型的值std tuple但发现它们在 C 中使用比在其他语言中
  • 在运行时将项目添加到 ToolStrip

    您好 我有一个带有 收藏夹 菜单的 ToolStripMenu 我想在运行时在 WinForms 应用程序中添加子项目 我有一个 datagridview 右键单击它会显示一个包含 添加到收藏夹 选项的上下文菜单 当该事件被触发时 我想使用

随机推荐