Вопрос

В C# мы можем определить универсальный тип, который накладывает ограничения на типы, которые можно использовать в качестве универсального параметра.Следующий пример иллюстрирует использование общих ограничений:

interface IFoo
{
}


class Foo<T> where T : IFoo
{
}

class Bar : IFoo
{
}

class Simpson
{
}

class Program
{
    static void Main(string[] args)
    {
        Foo<Bar> a = new Foo<Bar>();
        Foo<Simpson> b = new Foo<Simpson>(); // error CS0309
    }
}

Есть ли способ наложить ограничения на параметры шаблона в C++.


В C++0x есть встроенная поддержка этого, но я говорю о текущем стандарте C++.

Это было полезно?

Решение

Как кто-то уже упомянул, в C++0x это встроено в язык.А пока я бы порекомендовал Бьерн Страуструп's предложения по ограничениям шаблона.

Редактировать: Способствовать росту также имеет альтернатива сама по себе.

Редактировать2:Выглядит как концепции были удалены из C++0x.

Другие советы

Если вы используете С++ 11, вы можете использовать static_assert с std::is_base_of для этой цели.

Например,

#include <type_traits>

template<typename T>
class YourClass {

    YourClass() {
        // Compile-time check
        static_assert(std::is_base_of<BaseClass, T>::value, "type parameter of this class must derive from BaseClass");

        // ...
    }
}

«Неявно» — правильный ответ.Шаблоны эффективно создают сценарий «утиного набора текста» из-за способа их компиляции.Вы можете вызывать любые функции, которые хотите, для значения, введенного в шаблоне, и будут приняты только те экземпляры, для которых определен этот метод.Например:

template <class T>
int compute_length(T *value)
{
    return value->length();
}

Мы можем вызвать этот метод для указателя на любой тип, который объявляет length() метод для возврата int.Таким образом:

string s = "test";
vector<int> vec;
int i = 0;

compute_length(&s);
compute_length(&vec);

...но не по указателю на тип, который делает нет объявить length():

compute_length(&i);

Этот третий пример не скомпилируется.

Это работает, поскольку C++ компилирует новую версию шаблонизированной функции (или класса) для каждого экземпляра.Выполняя эту компиляцию, он выполняет прямую, почти макроподобную замену экземпляра шаблона в код перед проверкой типов.Если с этим шаблоном все по-прежнему работает, компиляция продолжается и в конечном итоге мы получаем результат.Если что-то не получается (например int* не декларируя length()), то мы получаем ужасную ошибку времени компиляции шестистраничного шаблона.

Вы можете установить тип защиты для IFoo, который ничего не делает, убедитесь, что он присутствует в T в Foo:

class IFoo
{
public:
    typedef int IsDerivedFromIFoo;
};

template <typename T>
class Foo<T>
{
    typedef typename T::IsDerivedFromIFoo IFooGuard;
}

Проверить Способствовать росту

Библиотека проверки концепции Boost (BCCL)

Библиотека Concept Check позволяет добавлять явные операторы и проверки концепции в стиле предлагаемое расширение языка C++.

Вроде, как бы, что-то вроде.Если вы используете static_cast для IFoo*, то создать экземпляр шаблона будет невозможно, если вызывающая сторона не передаст класс, который можно присвоить IFoo*.

Только косвенно.
Любой метод, который вы используете в фактически вызываемом методе, накладывается на параметр шаблона.

Ты можешь это сделать.Создайте базовый шаблон.Сделайте так, чтобы у него были только частные конструкторы.Затем создайте специализации для каждого случая, который вы хотите разрешить (или сделайте наоборот, если список запрещенных намного меньше списка разрешенных).

Компилятор не позволит вам создавать экземпляры шаблонов, использующих эту версию, с помощью частных конструкторов.

В этом примере разрешено создание экземпляров только с помощью int и float.

template<class t> class FOO { private: FOO(){}};

template<> class FOO<int>{public: FOO(){}};

template<> class FOO<float>{public: FOO(){}};

Это не короткий и элегантный способ сделать это, но это возможно.

Посмотрите на шаблон CRTP (шаблон любопытно-рекурсивного шаблона).Он предназначен для поддержки статического наследования.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top