【问题标题】:Partially filled template as parameter for template template [duplicate]部分填充的模板作为模板模板的参数[重复]
【发布时间】:2017-10-31 15:23:10
【问题描述】:

我有一个带有两个模板参数 (MyCollection) 的模板和另一个模板 (TCTools) 期望一个带有一个模板参数作为模板参数的模板。

我定义了一个“桥”(TypedCollection)来获取一个模板,该模板带有一个来自 MyCollection 的参数和一个参数作为它的第一个参数,目的是将其传递给模板模板。

这很好用,如果我使用带有固定类型的桥作为参数,但是从另一个模板调用它并使用另一个模板的参数将无法编译。

#include <iostream>
using std::size_t;

template <class Scalar, size_t size>
struct MyCollection
{
    MyCollection()
    {
        std::cout << "Made collection"
                  << std::endl
                  << "  " << __PRETTY_FUNCTION__
                  << std::endl;
    }
};

template <class Scalar>
struct TypedCollection
{
    template <size_t size>
    using value = MyCollection<Scalar, size>;
};

template <template <size_t> class TC>
struct TCTools
{
    static TC<10> *make_10_sized()
    {
        return new TC<10>();
    }
};

template <class S>
void test()
{
    // Will not compile
    TCTools<TypedCollection<S>::value>::make_10_sized();
}

int main()
{
    // works
    TCTools<TypedCollection<int>::value>::make_10_sized();

    test<int>();
    return 0;
}

GCC 给出以下注释:

expected a class template, got ‘TypedCollection<S>::value’

整件事让我很困惑。为什么 test() 中的调用没有编译,而 main() 中的调用按预期工作?是否可以进行测试?

【问题讨论】:

    标签: c++ c++11 templates template-templates


    【解决方案1】:
    TCTools<TypedCollection<S>::template value>::make_10_sized()
    

    很像typename(但令人困惑的不同),您必须区分value 是什么,否则编译器会假定它是一个值而不是类型或模板。

    它在S 被替换之前执行此操作。理论上,TypedCollection&lt;S&gt; 的特化可以使value 成为任何东西,编译器不会试图猜测。


    顺便说一句,如果您最终进行更多元编程,您会发现拥有模板、非类型和类型模板参数真的很痛苦。

    一种方法是将所有 3 种转换为类型。

    template<template<class...>class Z>
    struct ztemplate_t {
      template<class...Ts> using apply=Z<Ts...>;
    };
    // C++17
    template<auto x>
    using zvalue_t = std::integral_constant< std::decay_t<decltype(x)>, x >;
    // C++11
    template<std::size_t x>
    using zsize_t = std::integral_constant< std::size_t, x >;
    

    然后我们可以编写像apply 这样的模板,它将ztemplate 作为第一个参数并将其应用于其余参数,然后是zapply,即ztemplate&lt;apply&gt;

    一旦完成繁重的工作,TypedCollection&lt;T&gt; 将变为 partial_apply_t&lt; zMyCollection_t, T&gt;


    另一个是将所有 3 转换为 constexpr 值并进行 constexpr 值式元编程。

    在此之下,我们最终得到type_t&lt; decltype(zpartial_apply( zMyCollection, tag&lt;T&gt; ))&gt;


    但是对于小型的一次性库来说,这两个都过大了。

    【讨论】:

      猜你喜欢
      • 2021-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 1970-01-01
      相关资源
      最近更新 更多