c++ - 从 MSVC2015 更新 2 移植到 GCC 5.3 - SFINAE 错误

标签 c++ visual-studio-2015 c++14 porting gcc5

我目前正在移植我的库,但我的黑暗模板魔术无法使用 GCC 5.3 进行编译

此片段在使用 MSVC2015 更新 2 编译时按预期工作

template<typename vreal = 
    std::enable_if<std::is_vreal<vreal>::value, 
                   floatType>::type>
inline vreal foo(vreal bar)
{
    return bar;  
}

template<typename vreal = 
    std::enable_if<std::is_vreal<vreal>::value, 
                   floatType>::type>
struct bar { vreal i; };

GCC 提示“vreal 未在当前范围内定义(WTF?)”

到目前为止我尝试了什么:

将上面的模板片段重写为

template<typename vreal, 
         typename enable = typename std::enable_if<std::is_vreal<vreal>::value != 0>::type>

但这也行不通。它在代码中的中断时间很晚,我认为这是由于引入了额外的模板参数。

此外,我不明白为什么我必须引入与 0 的比较。如果没有它,gcc 会提示在 enabled_if 上缺少“类型”。

因此,主要问题是:如何在没有额外参数的情况下获得相同的 SFINAE 逻辑(仅当参数为 vreal 时才编译)。

我可以重写它以返回类型 SFINAE - 但我想避免做很多工作(区分函数、类、结构、类型定义/使用...),即使它被包装在宏中.

 template<typename vreal>
 typename std::enable_if<is_vreal<vreal>, vreal>::type inline vreal .....

最佳答案

这不是有效的 C++:

template<typename vreal = 
  std::enable_if<std::is_vreal<vreal>::value, 
               floatType>::type>
inline vreal foo(vreal bar)
{
  return bar;  
}

有很多原因。它使用 std 中的符号这不在 std 中( is_vreal ),这意味着您的程序格式错误。它使用 token floatType未定义(您确实发布了 [MCVE] 对吗?)。它使用 vreal在它进入范围之前,在 vreal 的定义中.

我不知道它应该是什么意思,除了您似乎相信它具有 SFINAE 魔法之外:它声明如果 vreal通过 is_vreal测试一下,应该是类型floatType默认情况下。但是为了达到这一点,您必须拥有类型 vreal已经,所以默认类型似乎并不重要。

此外,::type不是依赖上下文中的类型:,所以 std::enable_if<std::is_vreal<vreal>::value, floatType>::type应该提示你正在使用一个名为 ::type 的非类型在需要类型的上下文中。你需要做 typenam estd::enable_if<std::is_vreal<vreal>::value, floatType>::type .

您似乎还声明您正在使用宏来生成代码。这是一个糟糕的决定。

据我所知,只需删除 enable_if在大多数情况下,子句完全可以解决您的问题。

函数除外,因为可以重载,可以引入SFINAE helper。

完全放弃宏。无论如何,类和函数模板的工作方式有很大不同。

对于类/结构:

template<class vreal>
struct bar { vreal i; };

因为真的没有另一种选择——没有像函数那样重载结构/类的概念。

对于函数,我们需要 SFINAE 测试以便我们可以重载:

template<class T, class R=T>
using vreal_test = typename
  std::enable_if<std::is_vreal<T>::value, R>::type

template<class vreal>
inline vreal_test<vreal> foo(vreal bar)
{
  return bar;  
}

如果函数返回一个不同的类型,做

template<class vreal>
inline vreal_test<vreal,void> foo2(vreal bar)
{
  return;
}

您可以在扫除宏时执行此操作。

关于c++ - 从 MSVC2015 更新 2 移植到 GCC 5.3 - SFINAE 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37163053/

相关文章:

C++ [] 映射,可能通过模板

c++ - C++ 中的通用 block 等价物

visual-studio - 如何在 Visual Studio 2015 中使用 TypeScript 创建通用 Windows 应用程序?

C++1z 使用 std::initializer_list<int> 处理 == 测试,在自动函数中使用和不使用 const

c++ - unique_ptr 超出结构范围

c++ - 从 std::map 调用函数

c++ - 我们如何在 C++ 中组合返回多个值的函数

c# - 无法使用 "Precompile during publishing"选项部署网站

Cordova Windows 10 原生插件

c++ - Unresolved external symbol 错误将 DLL 链接到 LIB