为什么没有调用预期的函数?我是否错误地理解了类型特征?
Why isn't the expected function called? Do I understand type traits incorrectly?
我正在尝试学习类型特征的概念。我写了一些代码来测试我的理解:
#include <iostream>
#include <typeinfo>
#include <utility>
class Normal1 {};
class Normal2 {};
class Special {};
struct Normal_tag {};
struct Special_tag {};
template <typename T>
struct trait {
typedef Normal_tag Type;
};
template <>
struct trait<Special> {
typedef Special_tag Type;
};
template <typename T>
void handle_impl(T&& object, Normal_tag) {
std::cout << "normal called\n";
}
template <typename T>
void handle_impl(T&& object, Special_tag) {
std::cout << "special called\n";
}
// method 1: can't pass in rvalue
// template <typename T>
// void handle(T& object) {
// handle_impl(object, typename trait<T>::Type());
// std::cout << '\t' << typeid(T).name() << '\n'
// << '\t' << typeid(typename trait<T>::Type).name() << '\n';
// }
// method 2: always lvalue
// template <typename T>
// void handle(const T& object) {
// handle_impl(object, typename trait<T>::Type());
// std::cout << '\t' << typeid(T).name() << '\n'
// << '\t' << typeid(typename trait<T>::Type).name() << '\n';
// }
// method 3: try to use universal reference
template <typename T>
void handle(T&& object) {
// handle_impl(object, typename trait<T>::Type());
handle_impl(std::forward<T>(object), typename trait<T>::Type());
std::cout << '\t' << typeid(T).name() << '\n'
<< '\t' << typeid(typename trait<T>::Type).name() << '\n';
}
int main(int argc, char *argv[])
{
Normal1 n1;
Normal2 n2;
Special sp;
handle(sp); // This line
handle(n1);
handle(n2);
handle(Special());
handle(Normal1());
handle(Normal2());
return 0;
}
下面的输出不是我所期望的,我希望为左值和右值参数调用特殊方法:
normal called
7Special
10Normal_tag
normal called
7Normal1
10Normal_tag
normal called
7Normal2
10Normal_tag
special called
7Special
11Special_tag
normal called
7Normal1
10Normal_tag
normal called
7Normal2
10Normal_tag
我认为输出意味着 class Special
用于实例化。但是为什么我得到 Normal_tag
?为什么调用 handle(sp);
会这样?
我希望通用引用能够同时处理左值和右值参数,这是一种糟糕的方式吗?
当你调用handle(sp);
时sp是L值,所以在你的handle
模板中T
被推断为Special&
但你没有 Special&
的专业化
template <>
struct trait<Special&> {
typedef Special_tag Type;
};
因此你得到 正常调用 作为输出。
我正在尝试学习类型特征的概念。我写了一些代码来测试我的理解:
#include <iostream>
#include <typeinfo>
#include <utility>
class Normal1 {};
class Normal2 {};
class Special {};
struct Normal_tag {};
struct Special_tag {};
template <typename T>
struct trait {
typedef Normal_tag Type;
};
template <>
struct trait<Special> {
typedef Special_tag Type;
};
template <typename T>
void handle_impl(T&& object, Normal_tag) {
std::cout << "normal called\n";
}
template <typename T>
void handle_impl(T&& object, Special_tag) {
std::cout << "special called\n";
}
// method 1: can't pass in rvalue
// template <typename T>
// void handle(T& object) {
// handle_impl(object, typename trait<T>::Type());
// std::cout << '\t' << typeid(T).name() << '\n'
// << '\t' << typeid(typename trait<T>::Type).name() << '\n';
// }
// method 2: always lvalue
// template <typename T>
// void handle(const T& object) {
// handle_impl(object, typename trait<T>::Type());
// std::cout << '\t' << typeid(T).name() << '\n'
// << '\t' << typeid(typename trait<T>::Type).name() << '\n';
// }
// method 3: try to use universal reference
template <typename T>
void handle(T&& object) {
// handle_impl(object, typename trait<T>::Type());
handle_impl(std::forward<T>(object), typename trait<T>::Type());
std::cout << '\t' << typeid(T).name() << '\n'
<< '\t' << typeid(typename trait<T>::Type).name() << '\n';
}
int main(int argc, char *argv[])
{
Normal1 n1;
Normal2 n2;
Special sp;
handle(sp); // This line
handle(n1);
handle(n2);
handle(Special());
handle(Normal1());
handle(Normal2());
return 0;
}
下面的输出不是我所期望的,我希望为左值和右值参数调用特殊方法:
normal called
7Special
10Normal_tag
normal called
7Normal1
10Normal_tag
normal called
7Normal2
10Normal_tag
special called
7Special
11Special_tag
normal called
7Normal1
10Normal_tag
normal called
7Normal2
10Normal_tag
我认为输出意味着 class Special
用于实例化。但是为什么我得到 Normal_tag
?为什么调用 handle(sp);
会这样?
我希望通用引用能够同时处理左值和右值参数,这是一种糟糕的方式吗?
当你调用handle(sp);
时sp是L值,所以在你的handle
模板中T
被推断为Special&
但你没有 Special&
template <>
struct trait<Special&> {
typedef Special_tag Type;
};
因此你得到 正常调用 作为输出。