The literal "one" is const char [4] .
this code:
test("one")
Ideally, I would like to call test(const char (&)[4])
This works for test(const T&) (because const char (&) [4] can bind to const char (const&) [4] ).
But it cannot work for test(T t) because you cannot pass string literals by value. They are transmitted by reference.
However, const char[4] may fade to const char* , which may correspond to template<class T> void func(T t) .
The proof is in the pudding:
#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"); }
Examples of results (clang):
test_const for literal one T is ac and N is 4 test_const for literal three T is ac 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
Here is the version with demangled names (will compile on clang and 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"); }
expected output:
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*
Richard Hodges
source share