也就是说,我试图看看我是否可以区分:
const char * run_time;
和
"compile time"
我在下面写了代码,如图所示,当我尝试span>> “literal”它调用了const char *函数.
当我#if 0-out的const char *版本,模板版本被调用就好了.
如果我更改模板版本以获取文字的rvalue-reference(&&)参数,则不会编译.
如果我添加一个const char(& literal)[]非模板版本,const char *版本仍然是首选.删除const-char *版本,模板版本是首选.
你能解释一下吗尤其是:
>为什么const char *优先于const char(&)[N]?
>为什么const char(&)[N]优先于const char(&)[](非模板)?
>为什么const char(&&)[N]无法编译?
>是否有一种“正确的方法”来捕获文字字符串?
谢谢.
#include <iostream> using namespace std; #include <gsl/gsl> #include <type_name.h++> template<unsigned N> auto operator>>(gsl::span<const char*,-1>& spn,const char (&literal)[N]) -> gsl::span<const char*,-1>& { cout << "Got array: " << literal << endl; return spn; } auto operator>>(gsl::span<const char*,const char *literal) -> gsl::span<const char*,-1>& { cout << "Got const-char*: " << literal << endl; return spn; } #if 0 #endif int main(int argc,const char *argv[]) { auto spn = gsl::span<const char*>(argv,argc); cout << type_name<decltype(spn)>() << endl; // gsl::span<const char *,-1> cout << type_name<decltype("literal")>() << endl; // char const (&)[8] cout << type_name<decltype(("literal"))>() << endl; // char const (&)[8] auto helpx = "literal"; cout << type_name<decltype(helpx)>() << endl; // const char * spn >> "literal"; // Got const-char*: literal return 0; }
编辑:
如果重要,我正在编译:
c++ --std=c++14 -Iinclude -c -o main.o main.c++
而c说:
$c++ --version Apple LLVM version 8.0.0 (clang-800.0.42.1) Target: x86_64-apple-darwin16.5.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
解决方法
Why is
const char*
preferred overconst char (&)[N]
?
其原因相当技术性.即使一个字符串字符串从const char [N]到const char *的衰减是一个转换,它属于“lvalue转换”类别,因此被[over.ics.rank] / 3认为是一样好根本没有转换.由于任何一个超载都需要“无转换”,所以非模板重载胜利.
Why is
const char (&)[N]
preferred overconst char (&)[]
(non-template)?
不可能将未知绑定数组的引用绑定到已知绑定的数组类型的值.相反,对未知绑定数组的引用只能绑定到本身是未知绑定数组的值.
Why is
const char (&&)[N]
unable to compile?
字符串字面值是一个左值,所以我不知道为什么你会期望这个工作.
Is there a “right way” to capture literal strings?
您可以使用一个帮助函数模板,使用转发引用捕获其参数,以便不破坏任何类型信息(const char *对const char [N])),然后使用模板专门化分派类型.你可能还想使用SFINAE来确保它被禁用,除了const char *或const char [N]之外的其他任何东西.
template <bool b> struct f_helper; template <> struct f_helper<true> { void do_it(const char*) { puts("pointer"); } }; template <> struct f_helper<false> { template <std::size_t N> void do_it(const char (&)[N]) { printf("array of length %zd\n",N); } }; template <class T,class = typename std::enable_if<std::is_same<char*,std::decay_t<T>>::value || std::is_same<const char*,std::decay_t<T>>::value>::type> void f(T&& s) { f_helper<std::is_pointer<std::remove_reference_t<T>>::value>{}.do_it(s); }
Coliru链接:http://coliru.stacked-crooked.com/a/0e9681868d715e87