01/10/2018, 14:09
Bị C++ template đưa vào thế bí?
Mình có code như sau:
#include <vector>
using namespace std;
template<class Elem, template <class> class List>
void test(const List<Elem>& arr, const Elem& a) {}
int main() {
test(vector<int>(), 8);
}
Trình biên dịch báo lỗi no instance of function template “test” matches the argument list.
Nhưng mình viết thế này thì ok:
#include <vector>
using namespace std;
template<class Elem, template <class> class List, class Elem2>
void test(const List<Elem>& arr, const Elem2& a) {}
int main() {
test(vector<int>(), 8);
}
Chuyện trở nên vô cùng rắc rối nếu mình viết thế này, có chia ra Elem2 cũng không giúp được:
#include <vector>
#include <string>
using namespace std;
template<class Elem, template <class> class List>
void test(const List<basic_string<Elem>>& arr, const basic_string<Elem>& a) {}
int main() {
test(vector<string>(), string());
}
Có cách nào chỉ dùng 1 Elem thôi mà vẫn build được không?
Bài liên quan
Có lẽ bạn dùng compiler cũ nên nó chưa hỗ trợ toàn bộ tính năng của C++ 17 (đơn cử như gnu/gcc 6.x nó release date trước ngày release C++17 official).
wandbox.org
(Với C++ 17 thôi nhé)
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
#include #include using namespace std; template class List> void test(const List& arr, const Elem& a) { std::cout << a << std::endl; std::cou
C++17 có tính năng gì cho vấn đề này vậy?
Mình cũng không rõ vì bản thân mình không đi sâu vào template, từ ngày dùng template là mình đã dùng gcc/gnu 7.2 rồi.
Bạn có thể đọc feature của C++17 để xem các thay đổi.
Ref: http://www.bfilipek.com/2017/01/cpp17features.html
Vậy là phải ngồi update Visual Studio rồi
Xài MingW,msys2 hoặc đổi compiler của VS mình thấy thoải mái hơn
#include <vector> using namespace std; template<class Elem, template <class> class List> void test(const List<Elem>& arr, const Elem& a) {} int main() { test(vector<int>(), 8); }
Cái
std::vector<int>()
của bạn chỉ được xem như là 1 typeT
thôi (phiên bảnint
củastd::vector
, nên chỉ cầntemplate<class T>
là đủ,template <class> class List
là quá thừa thãi (và sai).Edit: Nếu argument là primitive type (float, double, int…) thì hạn chế dùng
const T &
.Vậy có cách nào để ràng buộc 2 typename đó không, hay chỉ cần viết
template <class T, typename U>
rồi mặc kệ? Nhu cầu của mình là sử dụng basic_string làm Elem.Đoạn code với
basic_string
bạn đưa ra ở trên là đúng (như @Dark.Hades đã nói, nó chạy được trên C++17). Đọc trên mạng họ bảo cú pháp này sẽ sai trước C++17, chính xác thì nó nằm ở đây:Giải quyết thì bạn có thể dùng C++17, khi đó code sẽ đúng, hoặc nếu dùng các standard cũ hơn C++17 thì phải tìm cách thay thế. Tạm thời mình nghĩ không ra nhưng nếu không quan trọng vấn đề container nào thì bạn có thể nhét luôn
std::vector
vàotest
cho đơn giản:http://en.cppreference.com/w/cpp/container/stack
cái template này giống
stack
hayqueue
nèthử gọi
std::stack<std::string, std::list<int>> s;
compile được, nhưng gọi
s.push("abc");
thì lại bị lỗi, còn gọis.push(11);
lại compile được. @_@cũ hơn C++17 thì có thể xài static_assert, nhưng mà lúc báo lỗi nó ko trỏ tới dòng lệnh gây ra lỗi
ví dụ như trên thì lúc báo lỗi nó nhảy tới dòng static_assert này chứ ko nhảy tới dòng gây ra lỗi, nhưng có thể truy ra được, được cái nó in ra cái lý do rõ ràng, ở đây là “Container::value_type must be T”
để xài với
std::string
thì xài string literalsvd:
sẽ gây ra lỗi:
vì “abc” được compiler hiểu là const char* chứ ko phải std::string. Sử dụng thêm namespace literals::string_literals là được: