如何在任意依赖类型上专门化模板

时间:2016-03-25 14:00:35

标签: c++ templates specialization

说,我有一些专门针对几种类型的模板,TypeMathcer,其中有type成员。

#include <memory>
#include <vector>

template <typename T>
struct TypeMatcher;

template <typename T>
struct TypeMatcher<T *>
{
    // making some type from T
    typedef std::shared_ptr<T> type;
};

template <typename T>
struct TypeMatcher<T&>
{
    // making other type from T
    typedef std::vector<T> type;
};

现在,我想创建另一个模板,并将其专门用于我从TypeMatcher获得的类型。如果我直截了当,就像这样

template <typename T>
struct MyNeedfullTemplate;

template <typename T>
struct MyNeedfullTemplate<typename TypeMatcher<T>::type>
{    
};

我收到编译错误:template parameters not deducible in partial specialization

如果使用using语法

,则会出现相同的错误
template <typename T>
using type_matcher_t = typename TypeMatcher<T>::type;

template <typename T>
struct MyNeedfullTemplate;

template <typename T>
struct MyNeedfullTemplate<type_matcher_t<T> >
{
};

我读到的问题partial specialization for iterator type of a specified container type的答案与我的问题非常相似,但仍然不确定是否存在一个反例让所有问题都变得毫无意义。现在我们还有全新的c ++ 14和c ++ 17标准,可以改变现状。那么,如果我确保专业化是独特的并且存在,那么比任何可能的参数都可以推导出来的那样呢?

2 个答案:

答案 0 :(得分:2)

原则上这是不可能的,没有花哨的C ++ 9999可以改变它。

你要求编译器做什么:

代码中有MyNeedfulTemplate<int>之类的用法。编译器需要MyNeedfulTemplate<U>的{​​{1}}定义。您已尝试提供表单

的部分特化
U = int

要查看此专业化是否适用,编译器必须检查template <typename T> struct MyNeedfullTemplate<typename TypeMatcher<T>::type> 所有可能的TypeMatcher<T> s ,并查找其中是否有任何一个具有嵌套的typedef T别名type。这不可能发生,因为“所有可能int s”的集合是无限的。好的,T没有这样的类型,TypeMatcher<int>TypeMatcher<int*>TypeMatcher<int**>也没有。但如果TypeMatcher<int***>怎么办?最好继续尝试......

还要记住,存在部分和完整的专业化,这意味着TypeMatcher<int****>本身可以是专门的。

简而言之,如果您拥有TypeMatcher而不是int,则没有方式可将TypeMatcher<X>::typeint相关联}。

你应该能够通过重新构造(反转)X来实现类似的东西:

TypeMatcher

答案 1 :(得分:1)

我认为你要做的是:

#include <iostream>

#include <memory>
#include <vector>
#include <utility>

template <typename T>
struct TypeMatcher;

template <typename T>
struct TypeMatcher<T *>
{
    // making some type from T
    typedef std::shared_ptr<T> type;
};

template <typename T>
struct TypeMatcher<T&>
{
    // making other type from T
    typedef std::vector<T> type;
};


template <typename T, typename = void>
struct MyNeedfullTemplate;

template <typename T>
struct MyNeedfullTemplate<TypeMatcher<T>, std::enable_if_t<std::is_same<typename TypeMatcher<T>::type, std::vector<std::remove_reference_t<T>>>::value>>
{
    static void report() { std::cout << "hello" << std::endl; }
};
int main()
{
    using matcher_type = TypeMatcher<int&>;
    using full_type = MyNeedfullTemplate<matcher_type>;
    full_type::report();

    return 0;
}

我能正确理解这个问题吗?