аргумент по умолчанию для специализации шаблонной функции - PullRequest
2 голосов
/ 04 августа 2010
template <typename T> void function(T arg1, 
    T min = std::numeric_limits<T>::min(),
    T max = std::numeric_limits<T>::max())
{
}

template <> void function<int>(int arg1, int min,int max)
{
}

int main(int argc,char* argv[])
{
    function<int>(1);
}

это дает синтаксическую ошибку C2689 и C2059 в строке аргумента функции по умолчанию для :: токена. но без специализации все нормально. и если я изменю аргумент по умолчанию и до сих пор занимаюсь специализацией:

template <typename T> void function(T arg1, 
    T min = T(0),
    T max = T(1))
{
}
template <> void function<int>(int arg1, int min,int max)
{
}

проблема ушла тоже.

Теперь, если я использую это так: function<int>(1,2,3); или function<float>(1.0f) это хорошо, так что кажется, что если шаблонная функция специализирована, мы должны переписать аргумент по умолчанию при ее вызове?

но во втором случае, когда я заменяю std::numeric_limits<T>::.. на T(..), при вызове function<int>(1) синтаксическая ошибка отсутствует, почему это так?

(я использую Visual Studio 2010 x64)

поскольку исходная проблема связана с ошибкой, теперь вопрос изменен на как ее обойти?

Ответы [ 3 ]

3 голосов
/ 04 августа 2010

В коде нет ничего плохого;Comeau Online, Intel C ++ 11.1 и g ++ 4.1.2 успешно скомпилируют его.

Я думаю, это ошибка компилятора.Недавно я представил связанный, но немного другой отчет об ошибке с компилятором Visual C ++ 2010.


В качестве обходного пути вы можете обернуть вызовы:

template <typename T>
T get_limits_min() { return std::numeric_limits<T>::min(); }

template <typename T>
T get_limits_max() { return std::numeric_limits<T>::max(); }

template <typename T> void function(T arg1, 
    T min = get_limits_min<T>(),
    T max = get_limits_max<T>())
{
}

Гадкий?Совершенно.


В ответ на сообщение об ошибке, о котором вы сообщили в Microsoft Connect, я опубликовал следующее:

Основной шаблон должен иметьпараметр, который имеет значение аргумента по умолчанию.Значением аргумента по умолчанию должна быть функция-член шаблона класса, не входящего в глобальное пространство имен.

Ниже приведен минимальный воспроизводимый код:

namespace N
{
    template <typename T>
    struct S
    {
        static T g() { return T(); }
    };
}

template <typename T> void f(T = N::S<T>::g()) { }

template <> void f<>(int) { }

int main()
{
    f<int>();
}

Компилятор выдает следующие ошибки:в строке, где определен основной шаблон:

error C2589: '::' : illegal token on right side of '::'
error C2059: syntax error : '::'

Интересно, что существует другая проблема, если шаблон класса находится в глобальном пространстве имен.С учетом следующего кода:

template <typename T>
struct S
{
    static T g() { return T(); }
};

template <typename T> void f(T = ::S<T>::g()) { }

template <> void f<>(int) { }

int main()
{
    f<int>();
}

Компилятор выдает следующую ошибку в строке, в которой определен основной шаблон:

error C2064: term does not evaluate to a function taking 0 arguments

Оба эти примера тестовых примера правильно сформированыПрограммы на C ++.

1 голос
/ 10 октября 2016

Как ответили здесь в https://stackoverflow.com/a/13566433/364084 и https://stackoverflow.com/a/27443191/364084,, это связано с минимальным и максимальным макросом, определенным в заголовке окна. Следующий код должен работать, предотвращая расширение макроса:

template <typename T> void function(T arg1, 
    T min = (std::numeric_limits<T>::min)(),
    T max = (std::numeric_limits<T>::max)())
{
}

template <> void function<int>(int arg1, int min,int max)
{
}

int main(int argc,char* argv[])
{
    function<int>(1);
}
0 голосов
/ 04 августа 2010

Успешно компилируется ... в Comeau Online, http://codepad.org,EDG Компилятор и G ++.

...