Computing a template argument from a string literal

I'm currently thinking about how best to restrict the general type of a template std::sting, as well as string literals. Therefore, I am comparing the inferred type with the desired type using std::is_same. In the case, std::stringit works right away. For a string literal meaning a char const array, it only works if I use std::decayfor a type, and then compare the result with the type char const *. If I directly compare the inferred type with what, in my opinion, should be, is_samereturns false, as shown in the following code example.

template <class TYPE>
void function(TYPE&& parameter)
{
  //this doesn't work as expected
  std::cout << typeid(TYPE).name() << " : " << typeid(char const [5]).name() << std::endl;
  std::cout << std::is_same<char const [5], TYPE>::value << std::endl;
  //this works as expected
  std::cout << typeid(std::decay_t<TYPE>).name() << " : " << typeid(char const *).name() << std::endl;
  std::cout << std::is_same<char const *, std::decay_t<TYPE>>::value << std::endl;
}

int main(int argc, char** argv)
{
  function("name");
  return 0;
}

The generated output is as follows:

char const [5] : char const [5]
0
char const * __ptr64 : char const * __ptr64
1

Now I wonder why it is_samereturns false in the first case, even if the types seem to be the same.

, , , std::is_same , std::decay (, ). , , , .

+6
3

char const [N], char const (&)[N].

:

std::cout << std::is_same<char const (&)[5], TYPE>::value << std::endl;

,

1) std::type_info, . , std::type_info, .

, is_same , type_info, , ,

std::is_same<int&, int>::value == false

, typeid , is_same .

+6

gcc:

template < class T >
constexpr std::string type_name()
{
    std::string p = __PRETTY_FUNCTION__;
    return p.substr( 43 + 10, p.length() - 100 - 1 - 10 );
}

:

std::cout << type_name<TYPE>() << " : " << type_name<char const [5]>() << std::endl;

:

A5_c : A5_c
0
const char (&)[5] : const char [5]

, std::remove_reference TYPE.

+2

This may be a compiler error. The compiler generates such object types specified by typeid in compiletime. The compiler will not compile array types for each length (from 0 to 2 ** n), so it compiles them if necessary and can "forget" about the duplicate. Try using a special template in which you separate the length from the type contained in it. This is not a type, but you can check if it matches the other.

    template<class T, size_t size> 
struct array_t{};

    template <class T, size_t size>
void function(T[size] parameter) {
    std::cout << typeid(array_t<T, size>).name() << " : " << typeid(array_t<char, 5>).name() << std::endl;
    std::cout << std::is_same<array_t<T, size>, array_t<char, 5>>::value << std::endl;
};
0
source

Source: https://habr.com/ru/post/1015216/


All Articles