Как исключить инстанцирование шаблона для конкретного типа

Есть полупустой класс Person с перемещающим конструктором и вторым принимающим универсальную ссылку (предполагается, что он будет использоваться для всех типов которыми можно инициализировать string), хочу, чтобы при передаче rvalue Person вызывался именно перемещающий конструктор и для этого запрещаю принимать параметры типа Person c помощью enable_if для другого конструктора. Так вот, в конструкторе выводится какой-то неведомый тип, а в main сравнение с результатом работы функции makePerson(якобы фабричная функция предоставляющая нам rvalue) происходит корректно. Почему так и как правильно? Помогите, пожалуйста. Решил написать этот код в качестве закрепления одной из глав книги Скотта Майерса (Эффективный и современный C++) и как всегда у него все круто, а у меня ничего не работает.

#include <string>
#include <utility>
#include <type_traits>

using namespace std;

class Person
{
private:
    string name;
public:
    template <typename T, typename = enable_if_t<!is_same<Person, decay_t<T>>::value>>
    Person(T&& obj) : name(forward<T>(obj)) 
    {
        cout << is_same<decay_t<T>, Person>::value << endl;
        cout << typeid(T).name() << endl;
        cout << "Cntr with forward" << endl;
    }
    Person(Person&& man) : name(move(man.name))
    {
        cout << "Moving cntr" << endl;
    }
};

Person makePerson(string name)
{
    return Person(name);
}


int main()
{
    Person me5(makePerson("f"));
    cout << is_same<typeof(makePerson("f")), Person>::value << endl;
    return 0;
}
//На консоль выводит:
//0
//NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
//Cntr with forward
//1

Ответы (1 шт):

Автор решения: HolyBlackCat

С кодом все нормально.

Вызвался первый конструктор с параметром std::string, перемещающий конструктор не вызвался из-за copy elision (который обязателен начиная с C++17).

typeid(...).name() печатает тип в нормальном виде только в MSVC, а в GCC и Clang-е результат нужно приводить в читаемый вид с помощью __cxa_demangle. Проще получить имя типа другим способом.

Еще, в C++ нет typeof. Используйте decltype.

→ Ссылка