Helpex - Trao đổi & giúp đỡ Đăng nhập
16

Hàm testbên dưới được nạp chồng cho các chuỗi trống giá trị, chuỗi không rỗng giá trị và chuỗi giá trị. Tôi đã cố gắng biên dịch với Clang và GCC nhưng trong cả hai trường hợp, tôi không có kết quả như mong đợi.

#include <iostream>

void test(const char (&)[1]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

template <unsigned long int N>
void test(const char (&)[N]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

void test(char*&&){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

int main(){
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);
}

Đầu ra với phiên bản clang 6.0.0-1ubuntu2 :

clang++ test.cpp -o test.out && ./test.out
void test(const char (&)[1])
void test(const char (&)[N]) [N = 5]
void test(char *&&)
void test(char *&&)

Đầu ra với g ++ (MinGW.org GCC-8.2.0-3) :

g++ test.cpp -o test.exe && test.exe
test.cpp: In function 'int main()':
test.cpp:15:11: error: call of overloaded 'test(char [1])' is ambiguous
  test(str1);
           ^
test.cpp:3:6: note: candidate: 'void test(const char (&)[1])'
 void test(const char (&)[1]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
      ^~~~
test.cpp:6:6: note: candidate: 'void test(const char (&)[N]) [with long unsigned int N = 1]'
 void test(const char (&)[N]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
      ^~~~
test.cpp:8:6: note: candidate: 'void test(char*&&)'
 void test(char*&&){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
      ^~~~

Câu hỏi của tôi là:

  1. Trình biên dịch nào là chính xác?
  2. Với Clang, tại sao test(str1)test(str2)chọn quá tải giá trị trong khi chúng là giá trị?
  3. Với GCC, tại sao cách gọi lại test(str1)mơ hồ?
  4. Có một quy tắc tiêu chuẩn nào cho tình huống này không?
  5. Làm thế nào để khắc phục hai cuộc gọi cuối cùng?

Cảm ơn bạn.

16 hữu ích 0 bình luận 1.2k xem chia sẻ
13
  1. Trình biên dịch nào là chính xác?

GCC là chính xác.

  1. Với clang, tại sao str1 và str2 chọn quá tải rvalue trong khi chúng là giá trị?

Clang là sai trên test(str1);, nó nên được mơ hồ. For test(str2);, str2có thể chuyển đổi hoàn toàn thành con trỏ, tức là phân rã mảng thành con trỏ. Giá trị được chuyển đổi char*là một giá trị. Vì lý do tương tự như # 3, các chuỗi chuyển đổi ngầm định có cùng xếp hạng, thì chức năng không phải mẫu được ưu tiên hơn; test(char*&&)đã được chọn.

  1. Với gcc, tại sao cuộc gọi với str1 là mơ hồ?

Để test(const char (&)[1])được gọi, cần phải chuyển đổi trình độ từ char[1]sang const char[1]; cho test(char*&&)được gọi, chuyển đổi mảng-to-con trỏ là bắt buộc. Cả hai đều đủ tiêu chuẩn là đối sánh chính xác và có cùng thứ hạng.

  1. Có một quy tắc tiêu chuẩn nào cho tình huống này không?

Xem xếp hạng của chuỗi chuyển đổi ngầm định trong giải quyết quá tảichuyển đổi ngầm định .

  1. Làm thế nào để khắc phục hai cuộc gọi cuối cùng?

Nó phụ thuộc vào ý định của bạn.

13 hữu ích 0 bình luận chia sẻ
3

Chuỗi ký tự không phải là giá trị. ( )

  1. Làm thế nào để khắc phục hai cuộc gọi cuối cùng?

Bạn có thể phân biệt mọi thứ với các chuyên môn mẫu:

#include <iostream>

template<typename C, std::size_t N>
void test(const C (&)[N]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C>
void test(const C (&)[1]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C, std::size_t N>
void test(const C (&&)[N]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C>
void test(const C (&&)[1]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C, std::size_t N>
void test(C (&)[N]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C>
void test(C (&)[1]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C, std::size_t N>
void test(C (&&)[N]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template<typename C>
void test(C (&&)[1]) { std::cout << __PRETTY_FUNCTION__ << std::endl; }

int main(){
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);
    test(std::move(str1));
    test(std::move(str2));
    const char str3[] = "";
    const char str4[] = "test";
    test(std::move(str3));
    test(std::move(str4));
}

cho

void kiểm tra (const C (&) [1]) [với C = char]
kiểm tra void (const C (&) [N]) [với C = char; long unsigned int N = 5]
void test (C (&) [1]) [with C = char]
void test (C (&) [N]) [with C = char; long unsigned int N = 5]
void test (C (&&) [1]) [with C = char]
void test (C (&&) [N]) [with C = char; long unsigned int N = 5]
void test (const C (&&) [1]) [with C = char]
void test (const C (&&) [N]) [with C = char; long unsigned int N = 5]

3 hữu ích 0 bình luận chia sẻ
1

Cảm ơn bạn @songyuanyao vì câu trả lời của bạn, giờ tôi đã hiểu tại sao lại test(char*&&)được chọn trong hai trường hợp cuối cùng. Tôi đã có thể loại bỏ sự mơ hồ với chuyên môn hóa mẫu trong lần quá tải đầu tiên nhờ câu trả lời @Darklighter.

Vì vậy, tôi đã giải quyết vấn đề của mình chẳng hạn như dưới đây:

#include <iostream>

template <unsigned long int N>
void test(const char (&)[N]){
    std::cout << __PRETTY_FUNCTION__ << " //non-empty literal" << std::endl;
}

template <>
void test(const char (&)[1]){
    std::cout << __PRETTY_FUNCTION__ << " //empty literal" << std::endl;
}

void test(char*&&){
    std::cout << __PRETTY_FUNCTION__ << " //string variable" << std::endl;
}

int main(){
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);
}

Đầu ra:

clang++ test.cpp -o test.out && ./test.out
void test(const char (&)[1]) //empty literal
void test(const char (&)[N]) [N = 5] //non-empty literal
void test(char *&&) //string variable
void test(char *&&) //string variable

g++ test.cpp -o test.exe && test.exe
void test(const char (&)[N]) [with long unsigned int N = 1] //empty literal
void test(const char (&)[N]) [with long unsigned int N = 5] //non-empty literal
void test(char*&&) //string variable
void test(char*&&) //string variable
1 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c++ language-lawyer overload-resolution value-categories , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading