I have a similar issue like the one found here but it might happen that I am still doing something different, so I will ask none-the less.
There are some types that will be tagged with a tag structure:
template<typename Geometry=void, typename Enable = void>
struct tag
{
typedef void type;
};
and point and triangle tags are introduced:
struct point_tag {};
struct triangle_tag {};
to construct the point type using the std::vector
:
template<>
struct tag<std::vector<double>>
{
typedef point_tag type;
};
and a triangle type as an alias template of the 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;
that is enabled if the argument passed as Point
parameter is really tagged with point_tag
,
and afterwards, I would like to tag all triangles with the triangle_tag
like this:
template <typename Point>
struct tag<triangle<Point>>
{
typedef triangle_tag type;
};
The std::array
is aliased and not composited/inherited because composition and inheritance causes problems with the initializer list construction . However, the compililation fails with the error
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’
If I don't rely on enabling the triangle
based on the Point
parameter being tagged, but do it for all types like this:
template<typename Point>
using triangle =
// This works, but there is no restriction on Point to be tagged with point_tag.
std::array<Point, 3>;
then the compilation works fine. However, then triangle is also a triangle , and I am using function overloading based on arbitrary properties of types to reduce the function template set from those functions for which the enable_if
fails. I am not relying on container interfaces for function templates to determine the viable template arguments because sometimes the implicit interfaces are exactly the same , but the operation semantics is different. For example, a triangle is a closed circular line segment (involves operation on 3 edges), and a point chain is an open-ended line segment (involves operations on 2 edges). All operations require a direct access operator which is the only requirement for the template parameter, which leads to ambiguity in function template instantiation when they are implemented without enable_if
restrictions - all covered in the linked article.
Here is the complete example .
Is there something I'm missing? How to get around this issue?
This works for me:
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];
};
What not use your Enable
template parameter ?
Something like:
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;
};
(ok, you repeat the enable_if
...)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.