为什么“literal’`鼓励在C参数类型匹配中朽烂到`const char *`?

前端之家收集整理的这篇文章主要介绍了为什么“literal’`鼓励在C参数类型匹配中朽烂到`const char *`?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在C14中玩过重载操作符,我试图匹配两种类型的参数:any-old-const-char *和a-string-literal.

也就是说,我试图看看我是否可以区分:

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 over const char (&)[N]?

其原因相当技术性.即使一个字符串字符串从const char [N]到const char *的衰减是一个转换,它属于“lvalue转换”类别,因此被[over.ics.rank] / 3认为是一样好根本没有转换.由于任何一个超载都需要“无转换”,所以非模板重载胜利.

Why is const char (&)[N] preferred over const 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

猜你在找的C&C++相关文章