Шаблон C в конструкторе

#c #visual-c #c 17

Вопрос:

У меня есть эта странная проблема, из-за которой мои коды c не смогли собраться; он мог собираться раньше, но я озадачен, почему я сталкиваюсь с этой проблемой сейчас;

ошибка: C2065: ‘T’: необъявленный идентификатор

в этой строке в конструкторе класса.

Diagnostic(int* pointer, std::function<QVariant(int*)> fn = [](int* pointer){return QVariant::fromValue(std::remove_pointer_t<T>(pointer)) ;})

 template<typename T>
class Diagnostic : QObject
{
    using T3 = std::remove_pointer_t<T>;
public:

    Diagnostic(int* pointer, std::function<QVariant(int*)> fn = [](int* pointer){return QVariant::fromValue(std::remove_pointer_t<T>(pointer));} )
    {
    }

};


int main(int argc, char *argv[])
{
    int * test = new int;
    *test=5;
    Diagnostic<int*> dg(test);
    delete test;
}
 

Однако, если приведенный ниже код в порядке

 template<typename T>
class Diagnostic : QObject
{
    using T3 = std::remove_pointer_t<T>;
public:

    Diagnostic(int* pointer)
    {
        std::function<QVariant(int*)> fn = [](int* pointer){return QVariant::fromValue(std::remove_pointer_t<T>(pointer)) ;};
    }

};
 

Но второй-это не то, что я хочу, так как мне нужно передать функцию
std::функция<QVariant(int*)> преобразуется в базовый класс во время создания экземпляра класса.
Любая помощь приветствуется. Я не знаю, почему возникает такая ошибка, когда ранее я мог создавать коды.

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

1. Пожалуйста, опубликуйте полное сообщение об ошибке. Заполнив пробелы, вот как далеко я мог бы продвинуться: godbolt.org/z/sMafG4bo9 . std::remove_ptr это не для удаления указательности из значения, а для удаления указателя из типа. Вы не можете бросить int* int такое заклинание. Оператор разыменования является *

2. если fromValue действительно статический метод? У меня есть сомнения в том, что код «ок» на самом деле в порядке

3. В чем заключается цель std::remove_pointer_t<T>(pointer) ? бросание int* в int ?

4. Скомпилируйте здесь нормально (с фиктивными объектами Qt).

5. @Jarod42 ОП хочет Diagnostic<int*> , и я думаю fromValue int* , что вам звонят, в то время как ОП хочет позвонить с int

Ответ №1:

Если удалить не соответствующие сведения, ошибка вызвана следующим кодом (MS VC ):

 template<typename T>
Diagnostic(int* pointer, std::function<int(int)> = [](int n) {
        int m = std::remove_pointer_t<T>();
        return m;
    });
// error C2065: 'T': undeclared identifier
 

Компилятор не распознает параметр шаблона класса T как тип внутри лямбда-тела, который объявлен как параметр по умолчанию. Вы можете обойти это, заранее объявив лямбду шаблона:

 template<typename U>
auto lam = [](int n) -> int {
    auto v = U(); // use of U template parameter
    return n;
};

template<typename T>
class Diagnostic {
public:
    Diagnostic(int* pointer, std::function<int(int)> = lam<T>); // T from the class
 

Использование типа шаблона класса T в самом параметре по умолчанию нормально.

Однако, если цель состоит в том, чтобы передать функцию базовому классу, вы можете написать:

 class QObject {
public:
    QObject(std::function<int(int)>) {}
};

template<typename T>
class Diagnostic : public QObject {
public:
    Diagnostic(int* pointer) : QObject([](int n) {
            int m = std::remove_pointer_t<T>();
            return m;
        }
    )
 

Попробуйте разобраться в происходящем, упростив выражения и тем самым снизив сложность.

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

1. Чтобы было ясно, использование параметра шаблона является законным; MSVC ошибается, если он отклоняет его.

2. Сообщение об ошибке в Microsoft developercommunity2.visualstudio.com/t/…

3. MS ответила: вам нужно /Zc:лямбда для компиляции исходного кода developercommunity2.visualstudio.com/t/…

4. Я отметил, что последний компилятор MSVC исправил это в обозревателе компиляторов.

5. Да, они исправили ошибку — хорошо тогда. developercommunity2.visualstudio.com/t/…