C ++ Неоднозначный вызов перегруженной функции - PullRequest
4 голосов
/ 22 октября 2011

У меня есть следующий код для «безопасного» strncpy () - в основном это оболочка автоматически принимает фиксированные размеры массивов для строковых буферов, поэтому вам не нужно делать дополнительную работу для их передачи (и это удобство безопаснеепотому что вы случайно не наберете неправильный размер для фиксированных буферов массива).

inline void MySafeStrncpy(char *strDest,size_t maxsize,const char *strSource)
{
    if(maxsize)
    {
        maxsize--;
        strncpy(strDest,strSource,maxsize);
        strDest[maxsize]=0;
    }
}

inline void MySafeStrncpy(char *strDest,size_t maxDestSize,
    const char *strSource, size_t maxSourceSize)
{
    size_t minSize=(maxDestSize<maxSourceSize) ? maxDestSize:maxSourceSize;
    MySafeStrncpy(strDest,minSize,strSource);
}

template <size_t size>
void MySafeStrncpy(char (&strDest)[size],const char *strSource)
{
    MySafeStrncpy(strDest,size,strSource);
}

template <size_t sizeDest,size_t sizeSource>
void MySafeStrncpy(char (&strDest)[sizeDest],
    const char (&strSource)[sizeSource])
{
    MySafeStrncpy(strDest,sizeDest,strSource,sizeSource);
}

template <size_t sizeSource>
void MySafeStrncpy(char *strDest,size_t maxDestSize,
    const char (&strSource)[sizeSource])
{
    MySafeStrncpy(strDest,maxDestSize,strSource,sizeSource);
}

Использование кода приводит к ошибке в Visual C ++ 2008 при компиляции:

char threadname[16];
MySafeStrncpy(threadname,"MainThread");

error C2668: 'MySafeStrncpy' : ambiguous call to overloaded function
>        could be 'void MySafeStrncpy<16,11>(char (&)[16],const char (&)[11])'
>        or       'void MySafeStrncpy<16>(char (&)[16],const char *)'
>        while trying to match the argument list '(char [16], const char [11])'

Что такоеЯ делаю что-то не так?

Кажется, что компилятор не может определить, следует ли трактовать строковый литерал "MainThread" как const char * или const char[11] при определении, какую функцию шаблона вызывать.

Мне бы хотелось, чтобы строковый литерал трактовался как const char[11] и выбирался вариант void MySafeStrncpy<16,11>(char (&)[16],const char (&)[11]), поскольку он является "самым безопасным".

Также есть еще два ограничения на ответы: 1) Iя не могу переключать компиляторы (код компилируется на других компиляторах) и 2) компания не разрешает мне использовать внешние библиотеки шаблонов для решения.

Ответы [ 3 ]

1 голос
/ 22 октября 2011

Согласно 13.3.3.1.1, преобразование массива в указатель имеет точное совпадение ранг, поэтому этот вызов функции может быть неоднозначным в стандартной спецификации.Если вам разрешено изменить определение:

template <size_t size>
void MySafeStrncpy(char (&strDest)[size],const char *strSource)

на:

template <size_t size, class T>
void MySafeStrncpy(char (&strDest)[size], T strSource)

как здесь , то, вероятно, это будет самый простой обходной путь.

0 голосов
/ 30 октября 2011

Когда вы используете вашу функцию:

MySafeStrncpy(threadname,"MainThread");

вы не передаете аргумент size_t между именем потока и "MainThread", но вы определили в определении функции.

это shudбыть примерно таким:

MySafeStrncpy(threadname, sizeof threadname, "MainThread");

, если вы не хотите передавать аргумент, установите его по умолчанию в определении функции.

0 голосов
/ 22 октября 2011

Перегрузки для char-array / const-char-array и char-array / const-char-pointer нельзя отличить друг от друга логикой разрешения перегрузки (по крайней мере, логикой Microsoft - этот код прекрасно компилируется вGCC. Не знаю, что стандарт говорит здесь.).Вы должны различать их каким-то образом, например, переименовав функцию для массивов или добавив фиктивный параметр.

Элегантным решением будет использование boost :: enable_if и boost :: is_array.

...