为什么我们有一个类型不匹配

Why does we have a type mismatch?

本文关键字:类型 不匹配 有一个 我们有 我们 为什么      更新时间:2023-10-16

我写了一个程序来查看如何在模板函数中推导字符串文字

#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*类型。

在其他两种情况下(passByReferancepassByConstRef),如果我们应用于推导的参数,std::remove_reference_tstd::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,它显式地导致数组类型衰减到指针:

如果T将类型命名为"U数组"或"对U数组的引用",则成员 typedef 类型为 U*

一些帮助程序,以更好地了解类型。CE: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");
}