【问题标题】:template function argument explicit type declaration模板函数参数显式类型声明
【发布时间】:2019-01-30 09:22:27
【问题描述】:

我有一个运算符重载列表,但我发现它们并没有按照我希望的方式运行。我将有问题的代码减少到几行来模拟问题。我有几个模板类型别名来帮助编译时间决策,一个模板函数(工作代码中的一个运算符,但这里只是一个通用函数)和一个名为 var 的类,它接受两个模板参数,一个 @987654322 @ 和 booltrue = 已知变量,false = 未知变量,只是提到这一点,以便以下代码 sn-p 中的命名约定有意义)。这是代码。

template<typename T>
using is_known = typename std::is_same<T, const var<T::ID, true> >::type;

template<typename T>
using is_unknown = typename std::conditional<is_known<T>::value, std::false_type, std::true_type>::type;

template<typename T>
using UK_if_UK = typename std::enable_if<is_unknown<T>::value, T>::type;

template<typename unknown_check_LHS, typename unknown_check_RHS>
constexpr const two_param_type<UK_if_UK<unknown_check_LHS>, UK_if_UK<unknown_check_RHS> > func(const unknown_check_LHS& lhs, const unknown_check_RHS& rhs)
{
    return two_param_type<unknown_check_LHS, unknown_check_RHS>
    (//generic construction goes here, unimportant...);
}

int main()
{
    constexpr const var<0u,true> firstvar(123);
    constexpr const var<1u,true> secondvar(456);

    func(firstvar,secondvar);
    func<std::decltype(firstvar),std::decltype(secondvar)>(firstvar,secondvar);
}

func() 的两次调用似乎与我相同,它们都应该失败(在工作代码中,一旦此函数 SFINAE 退出,还有其他选项)。但是,只有在我显式声明类型的第二次调用中,编译器才会抛出错误。它完美地编译了对func() 的第一次调用,更糟糕的是,它运行并返回类型为“已知”(var&lt;(some unsigned),true&gt;),即使返回类型中的类型别名应该 SFINAE 函数超出重载解析。我正在使用运算符,因此明确声明类型不是我的选择。然而,更重要的是,我想知道为什么这个函数没有 SFINAE 出来。任何帮助,将不胜感激。谢谢。

注意:具体错误为:

error: no matching function for call to 'func(const var<0u, true>&, const var<1u, true>&)'

另外,我已经测试了 is_knownis_unknownUK_if_UK 以正常工作,因此无需测试这些。谢谢。

【问题讨论】:

    标签: c++ c++11 templates constexpr sfinae


    【解决方案1】:

    对 func 的两次调用对我来说似乎相同

    错了。

    它们是不同的。

    这是一个常量问题。

    constexpr const var<0u,true> firstvar(123);
    constexpr const var<1u,true> secondvar(456);
    

    以及func()的签名如下

    template<typename unknown_check_LHS, typename unknown_check_RHS>
    constexpr /* ... */ func (const unknown_check_LHS & lhs,
                              const unknown_check_RHS & rhs)
    

    打电话

    func(firstvar,secondvar);
    

    unknown_check_LHSunknown_check_RHS 类型分别被检测为 var&lt;0u, true&gt;var&lt;1u, true&gt;

    请注意:var&lt;0u, true&gt;var&lt;1u, true&gt;,而不是 const var&lt;0u, true&gt;const var&lt;1u, true&gt;

    相反,解释如下类型

    func<decltype(firstvar), decltype(secondvar)>(firstvar,secondvar);
    

    (请注意:decltype(),而不是 std::decltype())、unknown_check_LHSunknown_check_RHS 分别解释为 const var&lt;0u, true&gt;const var&lt;1u, true&gt;

    请注意,现在类型是常量

    观察is_know是如何定义的

    template<typename T>
    using is_known = typename std::is_same<T, const var<T::ID, true> >::type;
    

    它将T 类型与常量类型进行比较。

    所以,在第一种情况下(模板类型不是常数),is_known 为假;在第二种情况下(使用常量模板类型),这是真的。

    【讨论】:

    • 谢谢,我从没想过这是问题所在。我之前的解决方案是将别名调用移动到函数参数列表而不是返回类型声明中,这最终奏效了,但是知道为什么以前的方法不起作用是非常有帮助的。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    相关资源
    最近更新 更多