C ++ pipeline segment with multiple output ports - type mapping

I am trying to create a pipeline for my project. I freely rely on the VTK pipeline concept. However, there are significant differences.

In my design, mapping the type of I / O connection was done using variative patterns and recursive inheritance (similar to CRTP). This allows me to manually determine which segments can be associated with which segments, passing a list of abstract base classes to the base filter / mapper classes. This in itself does not cause any problems.

I need to be able to work with custom (not necessarily std/ primitive) data types. The VTK pipeline passes pointers to objects that come from one of the VTK ( vtkAlgorithmObject) classes through pipeline segments. This allows a fairly natural implementation of the pipeline I / O interface with multiple connections. That is where my problem is.

Implementation of VTK output port function:

vtkAlgorithmOutput* vtkAlgorithm::GetOutputPort (int index) 

Unfortunately, I cannot return a custom class from the output port. Somehow, I need to have one (possibly overloaded) function getOutputPortthat will return another type based on a predefined index.

One way to do this is to use a combination of template arguments and overloading:

template<int N>
void getOutputPort(int& i)
{
    if (N == 0)
        i = 10;
    else if (N == 2)
        i = 20;
    else
        throw "Invalid template argument for the return type.";
}

template<int N>
void getOutputPort(string& str)
{
    if (N == 1)
        str = "qwerty";
    else
        throw "Invalid template argument for the return type.";
}

, , , , . std::unique_ptr. , .

, - ,

template<int N>
auto getOutputPort2()
{
    if (N == 0)
        return std::unique_ptr<int>(new int(10));
    else if (N == 1)
        return std::unique_ptr<string>(new string("qwerty"));
    else if (N == 2)
        return std::unique_ptr<int>(new int(20));
    else
        throw "Invalid template argument.";
}

" ". - ( auto)?

0
2

. , , . getOutputPort2() , . , . , , , , , -.

, , : . . .

template <typename T>
class A
{

public:

    // the Get Value we want
    template <int N>
    auto getValue()
        {
            return get_value_impl<N>::apply(*this);
        }

    // the general get value struct
    template<int N, typename = void>
    struct get_value_impl
    {
        static auto apply(A a)
            {
                throw "Invalid template argument.";
            }
    };

    // partial specialization 1
    template <typename S>
    struct get_value_impl<0, S>
    {
        static std::unique_ptr<double> apply(A a)
            {
                return std::unique_ptr<double>(new double(10.0));
            }
    };

    // partial specialization 2
    template <typename S>
    struct get_value_impl<1, S>
    {
        static std::unique_ptr<string> apply(A a)
            {
                return std::unique_ptr<string>(new string("Hello world!"));
            }
    };

};
0

- :

template<int N> struct helper_type {
    static_assert(N == 0 || N == 1 || N == 2, "Unexpected value");
    using type = typename std::conditional<N == 1,
        std::unique_ptr<std::string>,
        std::unique_ptr<int>>::type;
};

/* only specializations are valid */
template<int N>
typename helper_type<N>::type getOutputPort2() = delete; 

template<>
typename helper_type<0>::type getOutputPort2<0>()
{
    return std::unique_ptr<int>(new int(10));
}

template<>
typename helper_type<1>::type getOutputPort2<1>()
{
    return std::unique_ptr<std::string>(new std::string("asdf"));
}

template<>
typename helper_type<2>::type getOutputPort2<2>()
{
    return std::unique_ptr<int>(new int(20));
}
+1

Source: https://habr.com/ru/post/1568834/


All Articles