相关疑难解决方法(0)

重载分辨率和数组:应该调用哪个函数?

考虑以下程序:

#include <cstddef>
#include <cstdio>

void f(char const*&&)      { std::puts("char const*&&");      } // (1)
void f(char const* const&) { std::puts("char const* const&"); } // (2)

template <std::size_t N>
void f(char const (&)[N])  { std::puts("char const(&)[N]");   } // (3)

int main()
{
    const char data[] = "a";
    f(data);
}
Run Code Online (Sandbox Code Playgroud)

哪个f应该叫?为什么?

三个编译器的最新发布版本不同意这个问题的答案:

  • 当使用g ++ 4.5.2编译程序时调用(1)
  • 使用Visual C++ 2010 SP1编译程序时调用(2)
  • 使用Clang 3.0(trunk 127530)编译程序时调用(3 )

在不同的C++ 0x草案中,重载决策规则是否发生了很大变化?或者,这两个编译器真的完全错了吗?哪个重载是根据最新的C++ 0x草案选择的正确重载?

c++ arrays reference overload-resolution c++11

29
推荐指数
1
解决办法
1665
查看次数

左值参考和右值参考之间的重载分辨率

#include <iostream>

using namespace std;

void func(int (&ref)[6]) { cout << "#1" << endl; }
void func(int * &&ref) { cout << "#2" << endl; }

int main()
{
  int arr[6];
  func(arr); // g++(5.4): ambiguous, clang++(3.8): #2, vc++(19.11): #1

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这两个函数都是完全匹配.以下是标准的引用:

标准转换序列S1是比标准转换序列S2更好的转换序列

...

S1和S2是引用绑定(8.5.3),并且都不引用没有ref-qualifier声明的非静态成员函数的隐式对象参数,S1将rvalue引用绑定到rvalue,S2绑定左值引用.

这不是意味着第二个更好吗?

更新:

一个相关的问题.以下代码是它的简化版本.

#include <iostream>

using namespace std;

void func(int *&) { cout << "#1" << endl; }
void func(int *&&) { cout << "#2" << endl; }

int main()
{
  int arr[6]; …
Run Code Online (Sandbox Code Playgroud)

c++ overloading rvalue-reference language-lawyer

16
推荐指数
1
解决办法
423
查看次数

C++函数匹配优先级

我有关于c ++函数匹配优先级的简单问题.假设我有这样的代码:

#include <iostream>

void func(const char*)
{
    std::cout << "const char*" << std::endl;
}

template<int N>
void func(const char (&) [N])
{
    std::cout << "const char (&) [N]" << std::endl;
}

int main(int argc, char* argv[])
{
    func("Hello world");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

代码的结果是(with Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn)):

const char*
Run Code Online (Sandbox Code Playgroud)

我认为"Hello world"应该是文字类型const char[].为什么const char*版本的优先级高于const char (&)[]版本?

c++ function

12
推荐指数
1
解决办法
488
查看次数

数组衰减到指针和重载决策

我希望能够在重载分辨率中区分数组和指针:

class string {
public:
        string(const char* c_str);

        template<int N>
        string(const char (&str) [N]);
};


int main() {
        const char* c_str = "foo";
        string foo(c_str);      // ok will call string(const char*)

        string bar("bar");      // call string(const char*) instead of the array version
}
Run Code Online (Sandbox Code Playgroud)

到目前为止我发现的最好的是使用指针的引用而不是指针:

class string {
public:
        string(const char*& c_str);

        template<int N>
        string(const char (&str) [N]);
};


int main() {
        const char* c_str = "foo";
        string foo(c_str);      // ok will call string(const char*)
        string bar("bar");      // ok, will call …
Run Code Online (Sandbox Code Playgroud)

c++ arrays pointers

10
推荐指数
2
解决办法
819
查看次数

为什么第一个函数调用绑定到第一个函数?

为什么第一个函数call(cm(car);)绑定到第一个函数?

我知道第二个调用绑定到第二个函数,因为它是非模板,尽管两者都是完美的匹配.

如果第一个函数被定义为具有固定数组长度的非模板,则:

    void cm(const char (&h)[8]) {cout << "const char (&)[8]" << endl;}
Run Code Online (Sandbox Code Playgroud)

而不是它再次被选中在第二个(第二个调用将是不明确的那种方式).

码:

template<size_t N> void cm(const char (&h)[N]) 
    {std::cout << " const (&)[N] " << endl;}

void cm(const char * h)
    {cout << " const char * " << endl;}

int main()
{
    char car[] = "errqweq";
    const char ccar[] = "errqweq";
    cm(car);
    cm(ccar);
}
Run Code Online (Sandbox Code Playgroud)

输出:

 const (&)[N]
 const char * 
Run Code Online (Sandbox Code Playgroud)

c++ templates function language-lawyer overload-resolution

10
推荐指数
1
解决办法
153
查看次数

是否可以从模板参数中提取数组大小?

如果这是重复我道歉.我环顾四周,发现了类似的问题,但没有完全像这样.

如果我像这样实例化模板......

MyClass<int[10]> c;
Run Code Online (Sandbox Code Playgroud)

如何编写模板以访问类型和数组大小?我已经尝试了我能想到的一切,但我无法得到它.

我受到std :: function模板的启发,它允许你使用与函数原型相似的语法,比如......

std::function<int(MyClass&)> myfunc;
Run Code Online (Sandbox Code Playgroud)

所以我认为对阵列及其大小有类似的东西会很好.我可以使用任何最新的c ++特性(c ++ 11/14).

c++ templates template-meta-programming c++11

7
推荐指数
1
解决办法
781
查看次数

接口设计:采用字符串和字符数组的重载函数的安全性

假设我们有一个可以将东西写入输出的类

class Writer
{
public:
    int write(const std::string& str);
    int write(const char* str, int len);
    //...
};
Run Code Online (Sandbox Code Playgroud)

我很好,这很灵活,所有这一切,直到我意识到

char* buf = new char[n]; //not terminated with '\0'
//load up buf
Writer w;
w.write(buf);  //compiles!
Run Code Online (Sandbox Code Playgroud)

那是一个非常讨厌的错误.

我们可以用一些模板来修改

class WriterV2
{
public:
    int write(const std::string& str);
    int write(const char* str, int len);
    template<typename... Args>
    int write(const char*, Args...)
    { static_assert(sizeof...(Args) < 0, "Incorrect arguments"); }
    //...
};
Run Code Online (Sandbox Code Playgroud)

但这种方法存在问题

WriterV2 w;
w.write("The templating genius!"); //compile error
Run Code Online (Sandbox Code Playgroud)

我该怎么办?什么是更好的设计?

在任何人问之前,重载const char (&)[N] …

c++ interface

7
推荐指数
1
解决办法
90
查看次数

为什么 const char[] 与 std::ranges::range 的匹配比显式的 const char* 自由重载更好,以及如何修复它?

我想<<为任何人写一个泛型,range最后我得到了这个:

std::ostream& operator << (std::ostream& out, std::ranges::range auto&& range) {
    using namespace std::ranges;

    if (empty(range)) {
        return out << "[]";
    }

    auto current = begin(range);
    out << '[' << *current;

    while(++current != end(range)) {
        out << ',' << *current;
    }

    return out << ']';
}
Run Code Online (Sandbox Code Playgroud)

像这样测试:

int main() {
    std::vector<int> ints = {1, 2, 3, 4};
    std::cout << ints << '\n';
}
Run Code Online (Sandbox Code Playgroud)

它完美运行并输出:

[1,2,3,4]
Run Code Online (Sandbox Code Playgroud)

但是,当测试时:

int main() {
    std::vector<int> empty = {};
    std::cout << empty …
Run Code Online (Sandbox Code Playgroud)

c++ overload-resolution c++-concepts c++20 std-ranges

6
推荐指数
1
解决办法
152
查看次数

为什么 std::string_view 没有模板构造函数?

我正在阅读 的文档std::string_view,我注意到这些是构造函数:

constexpr basic_string_view() noexcept;
constexpr basic_string_view(const basic_string_view& other) noexcept = default;
constexpr basic_string_view(const CharT* s, size_type count);
constexpr basic_string_view(const CharT* s);
Run Code Online (Sandbox Code Playgroud)

为什么他们不介绍这个呢?

template<std::size_t n>
constexpr basic_string_view(const CharT(&s)[n]) : basic_string_view(s, n) {}
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,它将节省对 的调用strlen()。有什么原因没有被引入吗?

c++ c++17

5
推荐指数
1
解决办法
670
查看次数

不同编译器的奇怪行为,引用未知边界数组

情况1

以下代码在MSVC和GCC中产生截然不同的结果:

#include <iostream>

template <typename T>
void foo(const T&) {
#ifdef _MSC_VER
    std::cout << "foo(const T&): " << __FUNCDNAME__ << std::endl;
#else
    std::cout << __PRETTY_FUNCTION__ << std::endl;
#endif
}

void foo(const char*) {
    std::cout << "foo(const char*)" << std::endl;
}

int main() {
    extern char s[];
    foo(s);
}

char s[] = "abc";
Run Code Online (Sandbox Code Playgroud)

MSVC 2013 Update 5,MSVC 2015 Update 1(也在http://webcompiler.cloudapp.net上尝试了更新2,结果相同):

foo(const char*)
Run Code Online (Sandbox Code Playgroud)

GCC 5.3.0,Clang 3.7.0(DEMO):

void foo(const T&) [with T = char []]
Run Code Online (Sandbox Code Playgroud)

案例2

现在让我们删除模板:

#include …
Run Code Online (Sandbox Code Playgroud)

c++ g++ visual-c++ clang++ c++17

4
推荐指数
1
解决办法
98
查看次数