【问题标题】:Template specialization and alias template deduction difference模板特化和别名模板推导的区别
【发布时间】:2019-05-03 10:28:18
【问题描述】:

我很难理解在以下情况下如何进行扣减:

template<class Category, Category code>
struct AImpl
{ };

template<class Category, Category code>
struct AHelper
{
    using type = AImpl<Category, code>;
};

template<class Category, Category code>
using A = typename AHelper<Category, code>::type;

template<int code>
void doSomething(A<int, code> object)
{
}

以下是测试代码:

A<int, 5> a1;
doSomething(a1); // This does not compile
doSomething<5>(a1); // This compiles

为什么在这种情况下不推导出a1?

如果您改用以下方式修改 A:

template<class Category, Category code>
struct A
{ };

两者都有效。有谁知道为什么?

[编辑] 问题链接到Mixing aliases and template specializations

【问题讨论】:

    标签: c++ c++11 templates template-meta-programming template-argument-deduction


    【解决方案1】:

    为什么在这种情况下不推导出a1?

    因为doSomething 的模板参数出现在非推导上下文中。别名模板几乎完全代表它的别名。而你的定义如下:

    template<class Category, Category code>
    using A = typename AHelper<Category, code>::type;
    

    要推断code,编译器需要推断:: 左边的一些东西,这是一个非推断上下文。如果模板参数推导作为参数出现在范围解析运算符的左侧,则它甚至不会尝试推导。

    这不是没有理由的,这是一个未推断的上下文。请记住,模板可能是专门的。我可以添加这个:

    template<Category code>
    struct AHelper<int, code>
    {
        using type = BImpl<code>; // My own class!
    };
    

    编译器需要查看整个程序中的所有代码并尝试所有类型,以确保没有发生任何恶意事件,以确保a1 确实与typename AHelper&lt;Category, code&gt;::type 匹配。那是棘手的。因此,元函数映射只是单向街道。您不能要求编译器从目标类型中推断出源类型(或非类型参数)。

    【讨论】:

    • 感谢您的反馈,真的很有趣。我创建了 AHelper 以提供更大的灵活性,但如果以这种方式我失去了自动扣除,它可能不值得。有什么我可以使用的解决方法,也许以某种方式修改 doSomething?
    • @Saturnu - 您可以将其定义为接受AImpl。这样你就可以得到A 来帮助客户代码更容易地定义对象,而函数总是得到它需要的东西。不完美,但那是适合你的 C++。
    • 我已经考虑过了,但是如果有人创建自己的 AHelper 会怎样。该功能将不再起作用。每种 AHelper 专业化都需要重载,但这不是我想要的。
    • @Saturnu - 解决方案是命名空间。如果您将代码放在namespace yourLib {} 中,则不会与其他代码冲突。只要yourLib 足够独特。
    • 我的代码已经在命名空间中。我缺少一些东西
    猜你喜欢
    • 2017-01-20
    • 2018-08-26
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多