C 0x функция delete — удалить все, кроме определенных типов

#c 11 #c-strings #delete-operator #unicode-string

#c 11 #c-строки #удалить-оператор #unicode-строка

Вопрос:

В C 0x я могу сделать что-то вроде этого:

 double f(double x) { return x; }
template<class T>
  T f(T x) = delete;
  

Чтобы предотвратить f() вызов любого другого типа, кроме double .

То, что я пытаюсь сделать, похоже, однако, не совсем то же самое.

У меня есть функция, которая работает с массивами указателей. Например:

 template<class T>
  T* some_string_function(T* x);
  

Я хочу иметь возможность заставить T работать для char, char16_t и char32_t, но не для любого другого типа. Я думал, что C 0x delete был бы хорошим способом добиться этого. В принципе, я хочу иметь возможность запретить этой функции работать с любым типом, который не является одним из трех типов Unicode char , но я все еще хочу пользоваться преимуществами шаблонов функций, которые позволяют мне обобщать типы и избегать повторения кода.

Какой был бы наилучший способ решить эту проблему? Возможно ли это?

Комментарии:

1. Было бы хорошо, если бы вы могли = delete создать шаблон функции, а затем написать не удаляемую специализацию. Но из того, что я вижу из FDI, это невозможно.

Ответ №1:

Используйте boost::enable_if вместе с признаками типа.

 template<class T>
T* some_string_function(T* x, boost::enable_if<is_char_type<T>);
  

(предполагается, что is_char_type вы определяете свойство типа, которое оценивается как true для желаемых типов и false для всех остальных)

Комментарии:

1. В C 0x для этого не требуется boost, enable_if теперь является частью стандарта.

2. Ах, верно. По какой-то причине у меня сложилось впечатление, что enable_if это было исключено из C 0x

Ответ №2:

Вы могли бы сделать это с помощью type_traits:

 template<typename T>
typename enable_if<is_same<char, T>::value || is_same<char16_t, T>::value || is_same<char32_t, T>::value, T*>::type some_string_function(T *x)
{
    return x;
}
  

Хотя вам также придется специально указать const, если вы хотите разрешить это.

Ответ №3:

Я думаю, что лучший способ сделать это — использовать комбинацию static_assert и is_same (обе функции C 0x). Это также позволяет получить более понятное сообщение об ошибке при недопустимом вызове функции.

 #include <iostream>
using namespace std;

template<typename T> T* f(T*)
{
    static_assert
    (is_same<T, char>::value
     || is_same<T, char16_t>::value
     || is_same<T, char32_t>::value,
     "Invalid Type, only char pointers allowed");
}

int main()
{
    cout<<*f(new char('c'));//Compiles
    cout<<*f(new int(3));//Error
}