#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/…