模板参数在部分特化中无法推导

时间:2014-07-25 11:34:50

标签: c++ templates c++11

我有一个类似问题here,但可能会发生我仍然在做不同的事情,所以我会毫不犹豫地问。

有些类型会使用标记结构进行标记:

template<typename Geometry=void, typename Enable = void>
struct tag 
{
    typedef void type;
};

引入了点和三角标记:

struct point_tag {}; 
struct triangle_tag {}; 

使用std::vector构建点类型:

template<>
struct tag<std::vector<double>>
{
    typedef point_tag type; 
};

和三角形类型作为std::array的别名模板:

template<typename Point>
using triangle = 
typename std::enable_if
<
    std::is_base_of<typename tag<Point>::type, point_tag>::value,
    std::array<Point,3>
>::type;

如果作为Point参数传递的参数确实标记为point_tag,则启用

之后,我想用triangle_tag标记所有三角形,如下所示:

template <typename Point>
struct tag<triangle<Point>>  
{
    typedef triangle_tag type;
};

std::array是别名而不是合成/继承,因为组合和继承会导致initializer list construction出现问题。但是,编译失败并出现错误

g++ -std=c++1y main.cpp -o main 
main.cpp:31:8: error: template parameters not deducible in partial specialization:
 struct tag<triangle<Point>>  
        ^
main.cpp:31:8: note:         ‘Point’

如果我不依赖于根据被标记的triangle参数启用Point,而是针对所有类型执行此操作:

template<typename Point>
using triangle = 
// This works, but there is no restriction on Point to be tagged with point_tag.
std::array<Point, 3>;

然后编译工作正常。但是,三角形也是三角形,我使用function overloading based on arbitrary properties of types来减少enable_if失败的函数的函数模板集。我不依赖函数模板的容器接口来确定可行的模板参数,因为有时隐式接口完全相同,但操作语义不同。例如,三角形是闭合的圆形线段(涉及3条边上的操作),点链是开放式线段(涉及2条边上的操作)。所有操作都需要直接访问操作符,这是模板参数的唯一要求,这会导致在没有enable_if限制的情况下实现函数模板实例化时出现歧义 - 所有这些都包含在链接文章中。

这是complete example

有什么我想念的吗?如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

这对我有用:

template <typename Point>
struct triangle
{
    static_assert(std::is_same<typename tag<Point>::type, point_tag>::value, "triangle can only contain elements which model a point_tag.");

    Point&       operator[](std::size_t i) { return elems[i]; }
    Point const& operator[](std::size_t i) const { return elems[i]; }    
    Point elems[3];
};

答案 1 :(得分:1)

什么不能使用您的Enable模板参数?
类似的东西:

template <typename Point>
struct tag<
    std::array<Point, 3>,
    typename std::enable_if<
        std::is_base_of<
            typename tag<Point>::type,
            point_tag
        >::value
    >::type
>
{
    typedef triangle_tag type;
};

(好的,你重复enable_if ...)

Live example