Maxime Charrière
Maxime Charrière

Reputation: 775

Template specialization depending on a unknown typedef

In C++ I want to specialize a templated function. So far so good.
The problem is that the type that specialize my template depends on a typedef to which I don't have access.

Purpose explication

The user must first define a typedef for the class Surface_mesh by specifying some types in the template.

typedef CGAL::Surface_mesh<CGAL::Simple_cartesian<double>::Point_3> Mesh;

Mesh may vary according to the user's needs, but it will always have the following typedef:

Now I want to write a function that has a different implementation depending on Face_index, Vertex_index or Edge_index but not depending on the typedef Mesh. Here's how the user could use it:

std::cout << foo<void>() << std::endl;
std::cout << foo<Mesh::Face_index>() << std::endl;
std::cout << foo<Mesh::Vertex_index>() << std::endl;
std::cout << foo<Mesh::Edge_index>() << std::endl;

>> "Default foo() called"
>> "foo() for Face_index called"
>> "foo() for Vertex_index called"
>> "foo() for Edge_index called"

What I have tried

This first implementation work if foo had access to the Mesh tyedef, but this is not the case:

template <typename EI> //for Element Index
std::string foo(void)
{
    return "Default foo() called";
}

template <>
std::string foo<Mesh::Face_index>(void)
{
    return "foo() for Face_index called";
}

...

So I have tried something like that, but it doesn't work:

template <typename SM, typename EI> //for Surface Mesh and Element Index
std::string foo(void)
{
    return "Default foo() called";
}

template <typename SM>
std::string foo<SM::Face_index>(void)
{
    return "foo() for Face_index called";
}

...

Question

Do you know if it is possible to do what I want, and if so how to do it or do you have links to sites with explanations that could help me?


EDIT

Here is a simplified implementation of Surface_Mesh:

namespace CGAL
{
    // Implementation for Surface_mesh::Vertex_index
    class SM_Vertex_index
    {
        //...
    };

    // Implementation of Surfae_mesh::Face_index
    class SM_Face_index
    {
        //...
    };

    template <typename P>
    class Surface_mesh
    {
    public:
        typedef SM_Vertex_index Vertex_index;
        typedef SM_Face_index Face_index;
        //... (P is used in the code)
    };
}

Upvotes: 1

Views: 186

Answers (2)

t.niese
t.niese

Reputation: 40842

In CGAL Face_index is - except for the case when the documentation is created - just a typedef for SM_Face_idex (typedef SM_Face_index Face_index;) and the same for all surface meshes.

So theoretically you could just do:

template <typename T>
std::string foo(void)
{
    return "Default foo() called";
}

template <>
std::string foo<SM_Face_index>(void)
{
    return "foo() for Face_index called";
}

This would work for the current CGAL versions, but I don't see anything in the documentation, that this will be guaranteed to be that way in the future.

The problem is that the documentation claims that Face_index is an actual class defined within Mesh and not that it is a typedef of a type independent of the surface mesh.

Upvotes: 2

uscq
uscq

Reputation: 128

It is hard to get your mind, but I think the follow code may help you. It works in vs 2017.

// cls && cl x.cpp /EHsc && x

#include <iostream>

template<typename P, typename V, typename D> class ObjA
{
public:
    typedef P POSI;
    typedef V VERT;
    D extra;
};

typedef ObjA<int, double, float> Mesh;

template<typename T> void foo() noexcept
{
    std::cout << __FUNCSIG__ << "\n";
}

void foo() noexcept
{
    std::cout << __FUNCSIG__ << "\n";
}

int main()
{
    foo<Mesh::POSI>(); // void __cdecl foo<int>(void) noexcept
    foo<Mesh::VERT>(); // void __cdecl foo<double>(void) noexcept
    foo(); // void __cdecl foo(void) noexcept 
    return 0;
}

Upvotes: 1

Related Questions