我有一个类似问题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
限制的情况下实现函数模板实例化时出现歧义 - 所有这些都包含在链接文章中。
有什么我想念的吗?如何解决这个问题?
答案 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
...)