#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
}