Dosłowny "jeden" to const char [4]
.
ten kod:
test("one")
byłoby idealnie lubią nazywać test(const char (&)[4])
Działa to dla test(const T&)
(bo const char (&) [4]
może wiązać się const char (const&) [4]
).
Ale nie może działać dla test(T t)
, ponieważ nie można przekazywać literałów łańcuchowych według wartości. Są one przekazywane przez odniesienie.
Jednak const char[4]
może zepsuć się do const char*
, które można dopasować template<class T> void func(T t)
.
Dowód jest w puddingu:
#include <cstdint>
#include <iostream>
#include <typeinfo>
template <typename T, std::size_t N>
void test_const(const T(&t)[N])
{
std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << " and N is " << N << std::endl;
}
template <typename T>
void test_mutable(T &t)
{
std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}
template <typename T>
void test_const_ref(const T &t)
{
std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}
template <typename T>
void test_copy(T t)
{
std::cout << __func__ << " for literal " << t << " T is a " << typeid(T).name() << std::endl;
}
int main()
{
test_const("one");
test_const("three");
test_mutable("one");
test_mutable("three");
test_const_ref("one");
test_const_ref("three");
test_copy("one");
test_copy("three");
}
przykładowe wyniki (szczęk):
test_const for literal one T is a c and N is 4
test_const for literal three T is a c and N is 6
test_mutable for literal one T is a A4_c
test_mutable for literal three T is a A6_c
test_const_ref for literal one T is a A4_c
test_const_ref for literal three T is a A6_c
test_copy for literal one T is a PKc
test_copy for literal three T is a PKc
Oto wersja z nazwami demangled (będzie kompilować na brzękiem i gcc):
#include <cstdint>
#include <iostream>
#include <typeinfo>
#include <cstdlib>
#include <cxxabi.h>
std::string demangle(const char* name)
{
int status = -1;
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
template <typename T, std::size_t N>
void test_const(const T(&t)[N])
{
std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << " and N is " << N << std::endl;
}
template <typename T>
void test_mutable(T &t)
{
std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}
template <typename T>
void test_const_ref(const T &t)
{
std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}
template <typename T>
void test_copy(T t)
{
std::cout << __func__ << " for literal " << t << " T is a " << demangle(typeid(T).name()) << std::endl;
}
int main()
{
test_const("one");
test_const("three");
test_mutable("one");
test_mutable("three");
test_const_ref("one");
test_const_ref("three");
test_copy("one");
test_copy("three");
}
oczekiwana moc wyjściowa:
test_const for literal one T is a char and N is 4
test_const for literal three T is a char and N is 6
test_mutable for literal one T is a char [4]
test_mutable for literal three T is a char [6]
test_const_ref for literal one T is a char [4]
test_const_ref for literal three T is a char [6]
test_copy for literal one T is a char const*
test_copy for literal three T is a char const*
Tworzysz szablon z 2 różnymi 'T's,' char [4] '(' "one" ') i' char [6] '(' "three" '). Dlatego masz dwa nowe typy, oba zawierające 'f', dlatego oba te' f's muszą zostać zainicjalizowane. Stąd 'createFile()' jest wywoływane dwa razy. – BoBTFish
OK, ale dlaczego działa prosta wersja szablonu (bez stałej wartości stałej)? – mentalmushroom
Zanik wskaźnika (nie można pobrać tablicy według wartości). Co nie jest wystarczająco proste, aby opisać w komentarzu. Pozwolę komuś innemu opisać to w odpowiedzi. – BoBTFish