为什么我们有类型不匹配?
Why does we have a type mismatch?
我写了一个程序来查看字符串文字是如何在模板函数中推导出来的。
#include <iostream>
#include <string>
#include <type_traits>
template<typename T> void passByValue(T by_value)
{
std::cout << std::is_same_v<char const*, decltype(by_value)> << std::endl; // okay
}
template<typename T> void passByReferance(T &by_ref)
{
std::cout << std::is_same_v<char const*, std::remove_reference_t<decltype(by_ref)>> << std::endl;
}
template<typename T> void passByConstRef(const T &const_ref)
{
std::cout << std::is_same_v<char const*, std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>> << std::endl;
}
int main()
{
std::cout << std::boolalpha;
passByValue("string"); // true: good
passByReferance("string");// false ??
passByConstRef("string"); // false ??
return 0;
}
事实证明,仅针对 passByValue 的字符串文字推导为 const char*
类型。
在其他两种情况下(passByReferance和passByConstRef),如果我们应用推导的参数,std::remove_reference_t
和std::remove_const_t
,我想得到的是const char*
,对吗?
当我使用 std::decay_t
完成衰减时,我得到了类型匹配,这是为什么?
您超过了 const char[7]
而不是 const char *
。数组和指针不是一回事。他们经常感到困惑,因为数组很容易衰减到指向其第一个元素的指针。通过引用获取时,数组不需要衰减为指针。只有在第一种情况下,您的数组才需要衰减为指针。
以下测试为每种情况生成 true
:
#include <iostream>
#include <string>
#include <type_traits>
template<typename T> void passByValue(T by_value)
{
std::cout << std::is_same_v<char const*, decltype(by_value)> << std::endl;
}
template<typename T> void passByReferance(T &by_ref)
{
std::cout << std::is_same_v<char const[7], std::remove_reference_t<decltype(by_ref)>> << std::endl;
}
template<typename T> void passByConstRef(const T &const_ref)
{
std::cout << std::is_same_v<char [7], std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>> << std::endl;
}
int main()
{
std::cout << std::boolalpha;
passByValue("string");
passByReferance("string");
passByConstRef("string");
return 0;
}
编辑:至于 std::decay
,它明确导致数组类型衰减为指针:
If T
names the type "array of U
" or "reference to array of U
", the member typedef type is U*
.
一些助手可以更好地了解类型。行政长官:https://godbolt.org/z/6EFmIR
#include <type_traits>
template<class T>
struct Tis { Tis(); };
template<bool b>
struct Truth{ Truth(); };
template<typename T> void passByValue(T by_value)
{
Tis<T>{}; //call Tis<char const*>::Tis()
Truth<
std::is_same_v<char const*, decltype(by_value)>
>{}; // call Truth<true>::Truth()
}
template<typename T> void passByReferance(T &by_ref)
{
Tis<T>{}; // call Tis<char const [7]>::Tis()
Tis<decltype(by_ref)>{}; // call Tis<char const (&) [7]>::Tis()
Truth<
std::is_same_v<char const*, std::remove_reference_t<decltype(by_ref)>>
>{}; // call Truth<false>::Truth()
Tis<
std::remove_reference_t<decltype(by_ref)>
>{}; // call Tis<char const [7]>::Tis()
}
template<typename T> void passByConstRef(const T &const_ref)
{
Tis<T>{}; // call Tis<char [7]>::Tis()
Truth<
std::is_same_v<char const*, std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>>
>{}; // call Truth<false>::Truth()
Tis<
std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>
>{}; // call Tis<char [7]>::Tis()
}
void foo1(){
passByValue("string");
}
void foo2() {
passByReferance("string");
}
void foo3() {
passByConstRef("string");
}
我写了一个程序来查看字符串文字是如何在模板函数中推导出来的。
#include <iostream>
#include <string>
#include <type_traits>
template<typename T> void passByValue(T by_value)
{
std::cout << std::is_same_v<char const*, decltype(by_value)> << std::endl; // okay
}
template<typename T> void passByReferance(T &by_ref)
{
std::cout << std::is_same_v<char const*, std::remove_reference_t<decltype(by_ref)>> << std::endl;
}
template<typename T> void passByConstRef(const T &const_ref)
{
std::cout << std::is_same_v<char const*, std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>> << std::endl;
}
int main()
{
std::cout << std::boolalpha;
passByValue("string"); // true: good
passByReferance("string");// false ??
passByConstRef("string"); // false ??
return 0;
}
事实证明,仅针对 passByValue 的字符串文字推导为 const char*
类型。
在其他两种情况下(passByReferance和passByConstRef),如果我们应用推导的参数,std::remove_reference_t
和std::remove_const_t
,我想得到的是const char*
,对吗?
当我使用 std::decay_t
完成衰减时,我得到了类型匹配,这是为什么?
您超过了 const char[7]
而不是 const char *
。数组和指针不是一回事。他们经常感到困惑,因为数组很容易衰减到指向其第一个元素的指针。通过引用获取时,数组不需要衰减为指针。只有在第一种情况下,您的数组才需要衰减为指针。
以下测试为每种情况生成 true
:
#include <iostream>
#include <string>
#include <type_traits>
template<typename T> void passByValue(T by_value)
{
std::cout << std::is_same_v<char const*, decltype(by_value)> << std::endl;
}
template<typename T> void passByReferance(T &by_ref)
{
std::cout << std::is_same_v<char const[7], std::remove_reference_t<decltype(by_ref)>> << std::endl;
}
template<typename T> void passByConstRef(const T &const_ref)
{
std::cout << std::is_same_v<char [7], std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>> << std::endl;
}
int main()
{
std::cout << std::boolalpha;
passByValue("string");
passByReferance("string");
passByConstRef("string");
return 0;
}
编辑:至于 std::decay
,它明确导致数组类型衰减为指针:
If
T
names the type "array ofU
" or "reference to array ofU
", the member typedef type isU*
.
一些助手可以更好地了解类型。行政长官:https://godbolt.org/z/6EFmIR
#include <type_traits>
template<class T>
struct Tis { Tis(); };
template<bool b>
struct Truth{ Truth(); };
template<typename T> void passByValue(T by_value)
{
Tis<T>{}; //call Tis<char const*>::Tis()
Truth<
std::is_same_v<char const*, decltype(by_value)>
>{}; // call Truth<true>::Truth()
}
template<typename T> void passByReferance(T &by_ref)
{
Tis<T>{}; // call Tis<char const [7]>::Tis()
Tis<decltype(by_ref)>{}; // call Tis<char const (&) [7]>::Tis()
Truth<
std::is_same_v<char const*, std::remove_reference_t<decltype(by_ref)>>
>{}; // call Truth<false>::Truth()
Tis<
std::remove_reference_t<decltype(by_ref)>
>{}; // call Tis<char const [7]>::Tis()
}
template<typename T> void passByConstRef(const T &const_ref)
{
Tis<T>{}; // call Tis<char [7]>::Tis()
Truth<
std::is_same_v<char const*, std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>>
>{}; // call Truth<false>::Truth()
Tis<
std::remove_const_t<std::remove_reference_t<decltype(const_ref)>>
>{}; // call Tis<char [7]>::Tis()
}
void foo1(){
passByValue("string");
}
void foo2() {
passByReferance("string");
}
void foo3() {
passByConstRef("string");
}