2017-09-14 21 views
7

Cố gắng tạo bí danh make_shared trên một loại lớp cụ thể cho một hàm tạo cụ thể của lớp đó. nỗ lực hết sức mình:Bí danh Constexpr của hàm mẫu quá tải

class foo { public: foo(int x) : y(x) {} int y; }; 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

Sản lượng:

error: invalid static_cast from type ‘<unresolved overloaded function type>’ to type ‘std::shared_ptr<foo> (*)(int)’ 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

Tôi đang làm gì sai?

Trả lời

4

std::make_sharedMẫu chức năng biến thể. Bạn chỉ đang chỉ định <foo> làm thông số mẫu, nhưng bạn cũng cần có một số int ở đâu đó trong đó. Bất kể, cách tiếp cận của bạn bị ràng buộc thất bại vì nó phụ thuộc vào cách các đối số mẫu của make_shared được đặt ra và bởi vì nó thường cồng kềnh để làm việc với các tập quá tải trong C++.

gì tôi đề nghị là để tạo một hàm wrapper thay vì:

constexpr auto newfoo(int x) 
{ 
    return std::make_shared<foo>(x); 
} 

Theo tôi nó là dễ dàng hơn để viết, đọc và dễ hiểu. Nếu bạn thực sự cần SFINAE thân thiện và noexcept, bạn có thể repeat the body three times:

constexpr auto newfoo(int x) 
    ->   decltype(std::make_shared<foo>(x)) 
     noexcept(noexcept(std::make_shared<foo>(x))) 
     {   return std::make_shared<foo>(x); } 

Một vĩ mô có thể được sử dụng để thực hiện kê khai trên ít đau đớn.


Nếu bạn thực sự muốn có một con trỏ hàm, điều này dường như làm việc:

auto newfoo = 
    static_cast<std::shared_ptr<foo>(*)(const int&)>(
     &std::make_shared<foo, const int&>); 

Nhìn vào make_shared 's tuyên bố:

template< class T, class... Args > 
shared_ptr<T> make_shared(Args&&... args); 

Bạn cần cung cấp T=foo và một cái gì đó cho Args... . Vì Args... là gói tham chiếu chuyển tiếp, nó sẽ luôn hoặc là suy ra tài liệu tham chiếu lvalue hoặc tham chiếu rvalue. Đây là lý do tại sao <foo, const int&> là một tập hợp các tham số mẫu hợp lệ và <foo, int> thì không.

Như Zefick chỉ ra trong các ý kiến, tất cả điều này có thể được đơn giản hóa để:

constexpr auto newfoo = &std::make_shared<foo, const int&>; 

Dàn diễn viên là không thực sự cần thiết ở đây.

+1

+1, nhưng bạn có lẽ nên sử dụng 'const int &' thay vì 'int &&' trong ví dụ "nếu bạn thực sự muốn" của mình. Như là, 'const int i = 42; auto f = newfoo (i); 'sẽ không hoạt động. –

+0

@MilesBudnek: điểm tốt, đã thay đổi câu trả lời của tôi –

+2

'constexpr auto newfoo = std :: make_shared ' chỉ hoạt động. Tại sao chúng ta cần dàn diễn viên? – Zefick