【问题标题】:VS2017 template specialization error cannot convert from 'Class *(__cdecl *)(Args...)' to 'Class *(__cdecl *)(Args...)'VS2017 模板专业化错误无法从 'Class *(__cdecl *)(Args...)' 转换为 'Class *(__cdecl *)(Args...)'
【发布时间】:2017-07-24 12:25:55
【问题描述】:

这是我正在迁移到 VS2017 的代码库的简化版本。 以下代码在 VS2013 和 Intel C++ 编译器 2017 update 4 中编译,但在 VS2013 中不编译。

#include  <type_traits>

template<typename F, F f>
struct S1
{};
template<typename F, F f>
struct S2
{};

template<typename F, F f>
using BaseType = typename std::conditional<std::is_member_function_pointer<F>::value, S1<F, f>, S2<F, f>>::type;

template<typename Class, typename... Args>
Class * call_constructor(Args... args)
{
    return new Class(args...);
}

template<class Class, typename... Args>
struct Constructor : BaseType<Class *(*)(Args...), call_constructor<Class, Args...>>
{
    using ReturnType = Class *;
};

int main() {}

构造函数类的定义出现错误:

main.cpp(20): 错误 C2440: 'specialization': 无法从 'Class *(__cdecl *)(Args...)' 转换为 'Class *(__cdecl *)(Args...)' 注意:范围内具有此名称的函数都不匹配目标类型 注意:请参阅正在编译的类模板实例化“构造函数”的参考

如果我直接从 S1 或 S2 继承构造函数,错误就会消失。所以我认为问题在于 std::conditional 定义。

有什么想法吗?谢谢。

【问题讨论】:

  • template&lt;class T&gt;using type=T; 然后struct Constructor : BaseType&lt;type&lt;Class*(Args...)&gt;*, static_cast&lt;type&lt;Class*(Args...)&gt;&gt;(call_constructor&lt;Class, Args...&gt;&gt;) 试图将任何错误“向上”移动。恐怕您的代码仍在尝试确定 call_constructor 的重载,静态转换可能会有所帮助。
  • @Yakk 错误已更改 :) 错误 C2440: 'static_cast': 无法从 'Class *(__cdecl *)(Args...)' 转换为 'Class *(Args...)'
  • 在静态演员表中加一颗星...
  • @Yarr 回到原来的 :( 'static_cast': 不能从 'Class *(__cdecl *)(Args...)' 转换为 'Class *(__cdecl *)(Args.. .)'
  • 现在在() 中传递nullptr。这将消除是call_constructor 导致问题的可能性。或者传递一个不是具有固定参数的模板的固定函数。 (目标是进一步简化您的代码,看看我们是否可以生成一个更简单的示例)

标签: c++ templates visual-studio-2017 variadic-templates template-specialization


【解决方案1】:

在多次尝试重写代码后,我的一位同事想出了获胜的版本:

template<typename F, F f>
struct BaseType_
{
  using type = typename std::conditional<std::is_member_function_pointer<F>::value, S1<F, f>, S2<F, f>>::type;
};

template<typename F, F f>
using BaseType = typename BaseType_<F, f>::type;

template<class Class, typename... Args>
struct Constructor : BaseType_<Class*(*)(Args...), call_constructor<Class, Args...>>::type
{
  using ReturnType = Class *;
};

也许这通过延迟继承的实例化来解决问题 代码。我们不确定:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多