узнать тип авто

Я играю с общей лямбдой в С++ 1y, и меня часто смущает незнание типа переменной/параметра auto. Есть ли хороший способ узнать это?

В настоящее время я использую typeid(decltype(arg)).name()), но это не очень полезно. @encode дает немного лучший результат но все равно сложно разобрать

пример:

auto f = [](auto && a, auto b) {
    std::cout << std::endl;
    std::cout << typeid(decltype(a)).name() << std::endl << @encode(decltype(a)) << std::endl;
    std::cout << typeid(decltype(b)).name() << std::endl << @encode(decltype(b)) << std::endl;
};

int i = 1;
f(i, i);
f(1, 1);
f(std::make_unique<int>(2), std::make_unique<int>(2));
auto const ptr = std::make_unique<int>();
f(ptr, nullptr);

вывод

i  // it does not tell me it is reference
^i // ^ means pointer, but it is actually reference, kinda pointer though
i
i

i
^i
i
i

NSt3__110unique_ptrIiNS_14default_deleteIiEEEE
^{unique_ptr<int, std::__1::default_delete<int> >={__compressed_pair<int *, std::__1::default_delete<int> >=^i}}
NSt3__110unique_ptrIiNS_14default_deleteIiEEEE
{unique_ptr<int, std::__1::default_delete<int> >={__compressed_pair<int *, std::__1::default_delete<int> >=^i}}

NSt3__110unique_ptrIiNS_14default_deleteIiEEEE
r^{unique_ptr<int, std::__1::default_delete<int> >={__compressed_pair<int *, std::__1::default_delete<int> >=^i}}
Dn
*

В основном я хочу знать, что это параметр lvalue ref/rvalue ref/передается по значению и т. д.

и я использую Xcode 5.1.1


person Bryan Chen    schedule 24.04.2014    source источник
comment
Это может помочь: stackoverflow.com/questions/1488186/   -  person zch    schedule 24.04.2014
comment
@encode это не С++. Вы пишете C++ или Objective-C++? ^ means pointer, but it is actually reference, kinda pointer though Нет, это означает нечто совершенно другое.   -  person Lightness Races in Orbit    schedule 24.04.2014
comment
Пробовали ли вы использовать признаки типа для получения информации о типе? Как, например, std::is_reference? Полный список см. в этой ссылке.   -  person Some programmer dude    schedule 24.04.2014
comment
@LightnessRacesinOrbit да, это Objective-C++. .mm файл. но по моему опыту, @encode работает для большей части класса С++ (не для очень сложных классов шаблонов)   -  person Bryan Chen    schedule 24.04.2014
comment
@BryanChen: это два разных языка, поэтому ваш вопрос помечен неправильно. Пожалуйста исправьте.   -  person Lightness Races in Orbit    schedule 24.04.2014
comment
@JoachimPileborg да, это будет мое последнее средство   -  person Bryan Chen    schedule 24.04.2014
comment
@LightnessRacesinOrbit Мне действительно нужен ответ C++. Поскольку ObjC++ является надмножеством C++, я могу использовать его для кода ObjC++.   -  person Bryan Chen    schedule 24.04.2014
comment
Однако выполнение таких проверок часто является признаком плохого дизайна. Возможно, вы захотите проверить свой дизайн. Кроме того, вы можете прочитать о проблеме XY, потому что у вас есть решение, которое вы хотите использовать, но вам нужна помощь в его реализации, но вы не сообщаете нам, какую проблему вы на самом деле хотите решить с помощью своего решения. Могут быть другие, даже лучшие решения вашей первоначальной проблемы.   -  person Some programmer dude    schedule 24.04.2014
comment
@JoachimPileborg У меня нет оригинальной проблемы. Я изучаю, как работает общая лямбда. Я могу читать стандарт, но я хочу изучить его из кода.   -  person Bryan Chen    schedule 24.04.2014
comment
Это больше YX. Или, может быть, Rx. Вы бы поверили XYZ?   -  person Yakk - Adam Nevraumont    schedule 24.04.2014


Ответы (3)


Используйте функцию GCC __cxa_demangle:

std::string demangled(std::string const& sym) {
    std::unique_ptr<char, void(*)(void*)>
        name{abi::__cxa_demangle(sym.c_str(), nullptr, nullptr, nullptr), std::free};
    return {name.get()};
}

auto f = [](auto && a, auto b) {
    std::cout << demangled(typeid(decltype(a)).name()) << '\n';
    std::cout << demangled(typeid(decltype(b)).name()) << '\n';
};
person Konrad Rudolph    schedule 24.04.2014
comment
благодаря. очень полезно расшифровать NSt3__110unique_ptrIiNS_14default_deleteIiEEEE в std::__1::unique_ptr<int, std::__1::default_delete<int> >, но это не поможет мне узнать, ссылка это или нет - person Bryan Chen; 24.04.2014
comment
Вы знаете, языковая привязка может помешать присвоить std::free указателю типа void(*)(void*): лучше используйте лямбду. Или определите собственную политику struct default_free. - person Deduplicator; 03.09.2018
comment
@Deduplicator std::free не имеет языковой привязки в C++. См. §20.2 и §23.10.12. Но если бы языковая привязка была проблемой, вы могли бы соответствующим образом объявить свой тип указателя функции. - person Konrad Rudolph; 03.09.2018
comment
Я не уверен, что в [полезности] вы хотите указать. [контейнеры] 23.10, а 23.10.12 нет... - person Deduplicator; 03.09.2018
comment
Чтобы добавить к этому, абзац из [using.linkage]: То, имеет ли имя из стандартной библиотеки C, объявленное с внешней связью, extern "C" или extern "C++" связь, определяется реализацией. Для этой цели в реализации рекомендуется использовать extern "C++" связь.179 И указанное примечание: 179) Единственный надежный способ объявить сигнатуру объекта или функции из стандартной библиотеки C — включить заголовок, который объявляет это, несмотря на свободу действий, предоставленную в 7.1.4 стандарта C. - person Deduplicator; 03.09.2018
comment
@Deduplicator В моей версии (N4713, скомпилировано 16 января 2018 г.) номера разделов относятся к [library.c] и [c.malloc]. Раздел, который вы цитируете, предположительно относится к ::free и т. д., не std::free (который, как часть стандартной библиотеки C++, упоминается в предыдущем абзаце). Тем не менее, эта часть стандарта могла бы выиграть от разъяснения. - person Konrad Rudolph; 03.09.2018
comment
Но не указано, было ли имя сначала объявлено в глобальной области видимости, а затем импортировано в std, поэтому оно действительно относится и к std::clibraryfunction(). - person Deduplicator; 03.09.2018
comment
@Deduplicator Я прочитал это по-другому: да, вы правы, это не указано. Но я читал, что если реализация импортирует глобальные функции в std, то ей все равно нужно каким-то образом обеспечить их связь с C++. В противном случае объявления, показанные в [c.malloc] (и т. д.), были бы неполными, а [library.c], по-видимому, указывает, что это будет явно отмечено в стандартном документе. - person Konrad Rudolph; 03.09.2018

это то, с чем я закончил. в сочетании с @Konrad Rudolph answer и комментарием @Joachim Pileborg

std::string demangled(std::string const& sym) {
    std::unique_ptr<char, void(*)(void*)>
    name{abi::__cxa_demangle(sym.c_str(), nullptr, nullptr, nullptr), std::free};
    return {name.get()};
}

template <class T>
void print_type() {
    bool is_lvalue_reference = std::is_lvalue_reference<T>::value;
    bool is_rvalue_reference = std::is_rvalue_reference<T>::value;
    bool is_const = std::is_const<typename std::remove_reference<T>::type>::value;

    std::cout << demangled(typeid(T).name());
    if (is_const) {
        std::cout << " const";
    }
    if (is_lvalue_reference) {
        std::cout << " &";
    }
    if (is_rvalue_reference) {
        std::cout << " &&";
    }
    std::cout << std::endl;
};

int main(int argc, char *argv[])
{   
    auto f = [](auto && a, auto b) {
        std::cout << std::endl;
        print_type<decltype(a)>();
        print_type<decltype(b)>();
    };

    const int i = 1;
    f(i, i);
    f(1, 1);
    f(std::make_unique<int>(2), std::make_unique<int>(2));
    auto const ptr = std::make_unique<int>();
    f(ptr, nullptr);

}

и вывод

int const &
int

int &&
int

std::__1::unique_ptr<int, std::__1::default_delete<int> > &&
std::__1::unique_ptr<int, std::__1::default_delete<int> >

std::__1::unique_ptr<int, std::__1::default_delete<int> > const &
std::nullptr_t
person Bryan Chen    schedule 24.04.2014
comment
Хм. Почему type_helper является классом, а не шаблоном функции? - person Konrad Rudolph; 24.04.2014
comment
@KonradRudolph да, это должен быть шаблон функции ... Я пытался сделать это по-другому, но в итоге получил это. обновлено сейчас - person Bryan Chen; 24.04.2014
comment
Я уверен, что мне просто не хватает правильного заголовка, но мне трудно найти, какой из них ищет эту ошибку: print_type_inferred_by_auto.cpp:24:10: error: ‘abi’ has not been declared name{abi::__cxa_demangle(sym.c_str(), nullptr, nullptr, nullptr), std::free};. Я также получаю эту ошибку: print_type_inferred_by_auto.cpp:24:80: error: no matching function for call to ‘std::unique_ptr<char, void (*)(void*)>::unique_ptr(<brace-enclosed initializer list>)’ name{abi::__cxa_demangle(sym.c_str(), nullptr, nullptr, nullptr), std::free}; У меня есть компилятор C++11. Это С++14? - person Luv2code; 05.04.2016

В основном я хочу знать, что это параметр lvalue ref/rvalue ref/передается по значению и т. д.

Ну это легко.

template<class T>
struct is_lvalue:std::false_type {};
template<class T>
struct is_lvalue<T&>:std::true_type {};
template<class T>
struct is_literal:std::true_type {};
template<class T>
struct is_literal<T&&>:std::false_type {};
template<class T>
struct is_literal<T&>:std::false_type {};// I do not think needed

просто сделайте is_lvalue<decltype(x)>::value и is_value<decltype(x)>::value.

rvalue (временная или перемещенная ссылка) является небуквенным не-lvalue.

person Yakk - Adam Nevraumont    schedule 24.04.2014
comment
есть ли причина переопределить std::is_lvalue_reference и std::is_rvalue_reference? - person Bryan Chen; 24.04.2014
comment
@bryanchen Кроме возможности того, что в вашей std библиотеке этого не было, нет. - person Yakk - Adam Nevraumont; 24.04.2014