Виртуальный метод с неспециализированным аргументом шаблона - PullRequest
1 голос
/ 20 марта 2020
#include <iostream>
#include <array>
#include <vector>

using namespace std;

// Currently I have code much like this one:

template <const uint32_t N>
using VectorN = array<double, N>;


template <const uint32_t N>
class ITransformable {
public:
    virtual vector<VectorN<N>>&  positions() = 0;
};


class SomeTransformer {
public:
    template <const uint32_t N>
    void operator()(ITransformable<N>& transformable) const {
        /* implementation */
    }
};

// Then I want to create interface like this.

template <const uint32_t N>
class ITransformer {
public:
    virtual void operator()(ITransformable<N>& transformable) const = 0;
};

// And finally implement it for SomeTransformer:
// 
// Notice that class is not template, this is intentional.
//
// class SomeTransformer : public ITransformer<N> {
// public:
//     virtual void operator()(ITransformable<N>& transformable) const {
//         /* implementation */
//     }    
// }

На самом деле, сейчас это кажется мне невозможным. В противном случае этот класс наследовал бы неограниченное количество специализаций интерфейса ...

Но все же возможно ли это, по крайней мере, для конечного числа измерений N ?

template <template <typename> class C> кажется, связано, но я не могу понять, как применить это.

РЕДАКТИРОВАТЬ То, что я хочу, выглядит примерно так:

class SomeTransformer : 
    public ITransformer<2>, 
    public ITransformer<3>, 
    public ITransformer<4>, 
    ..., 
    public ITransformer<N> { 
    /* ... */ 
};

Для любого N когда-либо использовался в коде. Как я уже сказал, это кажется невозможным.

Ответы [ 2 ]

1 голос
/ 20 марта 2020

Вы можете достичь того, что вы хотите или почти что. Вот что я предлагаю:


#include <type_traits>
#include <utility>

template<std::size_t N>
struct ITransformer {};

template<class T>
class SomeTransformer_h { };

template<std::size_t... Indices>
class SomeTransformer_h<
    std::integer_sequence<std::size_t, Indices...>> :  
    public ITransformer<1 + Indices>... { };


template<std::size_t N>
class SomeTransformer : public SomeTransformer_h<
    std::make_index_sequence<N>
> { };

int main() {
    SomeTransformer<5> a;
    ITransformer<1>& ref = a;
    ITransformer<4>& ref2 = a;
    ITransformer<5>& ref3 = a;
}

Теперь для любого N он заставит SomeTransformer наследовать все ITransformer от 1 до N.

1 голос
/ 20 марта 2020

Поскольку N нигде не объявлено, вы не можете его использовать. Вам нужно что-то вроде:

class SomeTransformer : public ITransformer<5> {
public:
    virtual void operator()(ITransformable<5>& transformable) const {
        /* implementation */
    }    
};

или сделать его шаблоном класса:

template <uint32_t N>
class SomeTransformer : public ITransformer<N> {
public:
    virtual void operator()(ITransformable<N>& transformable) const {
        /* implementation */
    }    
};

ОБНОВЛЕНИЕ

Существует нет динамических c наследование в C ++. Поэтому то, чего вы хотите достичь, невозможно.

...