LINUX.ORG.RU

C++: а чё оно не компилируется?

 


0

3

https://godbolt.org/z/n3YWGMYfn

Хочу 4 конструктора для всех комбинаций (const, sign). Чё оно хочет?

Дадно, пример короче: https://godbolt.org/z/vn3TEn6s3 Тоже не хочет. Почему оно так себя ведёт?

В принципе понятно почему: на такой постановке задачи, сформулированной таким кодом, шаблонный движок не осилил подобрать T = char. Оно пыталось подобрать T = char[6], у него не взлетело и оно бросило попытки. Чё-то такое. Оно дуро?



Последнее исправление: lesopilorama (всего исправлений: 2)

Оно дуро?

>#include <iostream>

printf(«C s\n»);

пишет шаблон - забывает ромбовидные скобки.

АРЯЯ ЯЗЫГ ПЛОХОЙ

    const signed char var[100]{"TEST"};
    Data<signed char> d((signed char*)"hello");
    Data<signed char> d2(var);
Ygor ★★★★★
()
Ответ на: комментарий от PRN

Не вижу там ни одного указателя на ‘char’.

а надо бы. строковые константы в си и плюсах, это нуль терминированные си строки, а тип - константый указатель на си строку. то есть const char*.

его он и подставил в шаблон. и компилятор ругнулся.

alysnix ★★★
()
Ответ на: комментарий от PRN

Строковая константа - это, внезапно, массив charов

да пофиг. ни от массива символов, ни от константного указателя на char нельзя взять signed/unsigned. то есть никакой из вариантов типа параметра шаблона не привел к успеху.

alysnix ★★★
()
Ответ на: комментарий от alysnix

Нет, если не заниматься тем, чем я пытаюсь, а написать просто

template <typename T>
struct Blabla {
    explicit BlaBla(const T *) {}
};

то в случае

Blabla xxxx("sobaka");

T будет равно char. Можете проверить/попробовать.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)
Ответ на: комментарий от lesopilorama

T будет равно char. Можете проверить/попробовать.

так о чем и речь.

в формальный параметр темплейта вида «const T*», подставляется константа типа «const char[7]», совместимая c «const char*».

разумеется, если сопоставить «const T*» с «const char*», получится что T === char.

alysnix ★★★
()

а что, маны читать сейчас не принято?

https://en.cppreference.com/w/cpp/language/types

signed char — type for signed character representation.

unsigned char — type for unsigned character representation. Also used to inspect object representations (raw memory).

char — type for character representation which can be most efficiently processed on the target system (has the same representation and alignment as either signed char or unsigned char, but is always a distinct type)

иными словами, char, signed char и unsigned char - это 3 разных типа. А у тебя все конструкторы помечены как explicit и ни один не принимает char. Ну, типа, оно и не должно компилироваться.

Lrrr ★★★★★
()

Во-первых: char, signed char и unsigned char - это три разных типа. Указатели на них в норме друг в друга не конвертируются. Такие вот странности строк в плюсах, х.з. зачем.

Во-вторых: ты сам определись, при вызове Data(uint8_t*), например, компилятор тебе какой тип должен создавать? T в шаблоне должен быть signed или unsigned? Когда определишься - напиши deduction guide для класса, и он будет делать то, что ты ему скажешь.
Но с char* это проблему не решит, т.к. см. во-первых.

Если тебе надо отделить как-то указатели на знаковые от указателей на беззнаковые, то не делай два отдельных типа, а разделяй концептами или requires’ами, будет удобнее.

Если ты хочешь просто универсальный конструктор, то сделай его отдельным шаблоном, по-умолчанию равным T, с проверкой, что U* ковертируется в T*.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от lesopilorama

вот так компилируется

#include <iostream>
#include <type_traits>

template <class T>
class Data {
public:
    using T_sig = typename std::make_signed_t<T>;
    using T_uns = typename std::make_unsigned_t<T>;

    const T_uns *data_ = nullptr;

    explicit Data(const T_uns *_ptr)
    : data_(_ptr) {
        
    }
};


int main() {

    Data<char> t2((const unsigned char*)"bubulka");
    
    //std::cout << std::is_same< decltype(t1)::T_sig, decltype(t2)::T_sig >::value << std::endl;
    
    return 0;
}

он не может понять что за тип T вообще у него. видимо потому что у конструктора уже тип выведенный из T.

потому что вообще говоря, если тип TT выведен из некого T, вовсе не обязательно есть обратное преобразование, а оно ему надо.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от lesopilorama

вот с чего ты взял что можно вывод типа, провернуть в обратную сторону? тут скорее всего непонятки у него, как сделать обратное преобразование от make_unsigned. он даже думать об этом не хочет. ему просто на это плевать.

alysnix ★★★
()
Ответ на: комментарий от anonymous

Когда читаешь тред и повторяешь про себя «Спасибо, Г-ди, что не сотворил меня программистом на С++»

Такой код редко пишут. В реальной корпорации за него кочергой по морде дадут со всей силы, так что в быту с таким обычно не мучаются. У нас есть коллега, который пытается писать мегаконцептуальные шаблонные опердени 5-го порядка, но наверное его скоро зарубят топором. Это скорее спортивный интерес. Была попытка сделать класс, который работает для char и для unsigned char, но без завязки на char.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 2)
Ответ на: комментарий от lesopilorama

Лайф хак. Если перестать пользоваться при разработке всякими г0внокомпиляторами и взять нормальный, то он будет тебе писать в чем там проблема.

<source>:21:10: error: no viable constructor or deduction guide for deduction of template arguments of 'Data'
   21 |     Data t2((const unsigned char*)"bubulka");

У тебя T вывелся не тот, что ты ожидаешь и как следствие нет подходящего конструктора.

Скорее даже, с данными конструкторами, компилятор T вывести без гайда не может.

Добавь под объявление класса:

template<class T>
Data(T*) -> Data<T>;
PRN
()
Последнее исправление: PRN (всего исправлений: 3)