Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does we have a type mismatch?

I have written a program to see, how string literals been deduced in template functions.

#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;
}

It turns out that, only for the passByValue the string literals deduced to const char* type.

In other two cases(passByReferance and passByConstRef), if we apply to the deduced arguments, std::remove_reference_t and std::remove_const_t, what I we suppose to get is const char*, is that correct?

I get a type match when I do complete decay using std::decay_t, why is that?

like image 216
Const Avatar asked Jan 01 '23 08:01

Const


1 Answers

You are passing const char[7] not const char *. Arrays and pointers are not the same things. They are often confused because arrays easily decay to pointers to their first element. When taken by reference, arrays don't need to decay to pointers. Only in the first case does your array need to decay to a pointer.

The following tests produces true for each case :

#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;
}

Edit : As for std::decay, it explicitly causes array types to decay to pointers :

If T names the type "array of U" or "reference to array of U", the member typedef type is U*.

like image 190
François Andrieux Avatar answered Jan 03 '23 20:01

François Andrieux