2015-03-30 13 views
14

Biến là v trong mã mẫu bên dưới odr-used?Mẫu đối số không loại cho loại tham chiếu và được sử dụng odr

extern void* v; 

template<void*&> 
void f() {} 

int main() 
{ 
    f<v>(); 
} 

Tôi tìm thấy mẫu này trong Boost ML.

cf. http://lists.boost.org/Archives/boost/2011/04/180082.php

Nó nói rằng boost::enabler không bao giờ được xác định, nhưng kêu vang bác bỏ nó như là một lỗi liên kết nếu -g tùy chọn được cung cấp.

cf. http://melpon.org/wandbox/permlink/nF45k7un3rFb175z

Mã mẫu ở trên là phiên bản rút gọn của mã Boost ML và clang cũng từ chối nó.

cf. http://melpon.org/wandbox/permlink/ZwxaygXgUhbi1Cbr

Tôi nghĩ (nhưng tôi không chắc chắn) mà đối số mẫu không loại cho loại tài liệu tham khảo là ODR-sử dụng ngay cả khi họ không được gọi trong mẫu cơ thể của họ để mô hình Boost ML của là vô hình thành.

Sự hiểu biết của tôi có đúng không?

Trả lời

2

[basic.def.ODR]/3:

Một biến x có tên xuất hiện như một biểu hiện khả năng đánh giá lại exODR-sử dụng bởi extrừ khi áp dụng vế trái-to-rvalue chuyển đổi (4.1) để x sản lượng một biểu thức hằng số (5,19) [..]

Thật không may, áp dụng chuyển đổi lít để v vào thời điểm này sẽ không mang lại một biểu thức hằng - [expr.const]/2 :

Một có điều kiện thể hiệne là một biểu thức cốt lõi liên tục trừ khi việc thẩm định e, theo các quy tắc của máy trừu tượng (1.9), sẽ đánh giá một trong những biểu hiện sau: [..]

- một chuyển đổi vế trái-to-rvalue (4.1) trừ khi nó được áp dụng cho

  • một glvalue non-volatile của thiếu hoặc liệt kê loại đó đề cập đến một đối tượng const non-volatile với trước khởi, khởi tạo với một biểu thức hằng [..], hoặc

  • một glvalue non-volatile đó đề cập đến một đối tượng non-volatile định nghĩa với constexpr, hoặc là đề cập đến một sub-object không thể thay đổi của một đối tượng như vậy, hoặc

  • một glvalue non-volatile của literal loại đó đề cập đến một phi đối tượng dễ bay hơi có tuổi thọ bắt đầu trong quá trình đánh giá e;

Tuy nhiên, mặc dù việc thực hiện đề nghị của Matt là không đúng, ý tưởng chắc chắn là. Một cách đơn giản để sử dụng phương pháp này được thể hiện trong this answer, sử dụng một mẫu trình trợ giúp. Trong trường hợp của bạn, hãy thử

template <bool cond, int id=0> 
using distinct_enable_if = 
    typename std::enable_if<cond, std::integral_constant<int,id>*>::type; 

class test 
{ 
public: 
    template< class... T, 
      distinct_enable_if<sizeof...(T) == 10> = nullptr> 
    test(T&&...) {} 

    template< class T, 
      distinct_enable_if<std::is_arithmetic<T>{}> = nullptr> 
    operator T() const { return T{}; } 

    /* Note the additional template argument: 
    It ensures that the template parameter lists are not identical, 
    and the ODR isn't violated */ 
    template< class T, 
      distinct_enable_if<std::is_pointer<T>{}, 1> = nullptr> 
    operator T() const { return T{}; } 
}; 

Demo.

+0

Cảm ơn. Tôi chắc chắn rằng sự hiểu biết của tôi là chính xác. Nhưng tôi không chắc chắn làm thế nào để sử dụng một mẫu helper. Tôi nên sử dụng mẫu trình trợ giúp cho trường hợp của 'boost :: enable_if_c' ở đâu? –

+0

@MitsuruKariya Mở rộng câu trả lời. – Columbo

7

Tôi tin rằng vodr-used. f<v> là một mẫu-id (14,2) mà mẫu đối số là một id-biểu (5.1.1) - một hình thức biểu hiện. Đó là rõ ràng không phải là một toán hạng unevaluated (nó không xuất hiện như một toán hạng của typeid, sizeof, noexcept hoặc decltype), vì vậy nó có khả năng đánh giá mỗi 3.2/2:

3,2/2 Một biểu hiện được có khả năng đánh giá trừ khi nó là một toán hạng unevaluated (khoản 5) hoặc một subexpression đó ...

Tại thời điểm đó, chúng tôi có

3,2/3 Một biến x có tên xuất hiện như một biểu hiện khả năng đánh giá lại extrừ [một điều kiện mà không xuất hiện để áp dụng ở đây như là không có giá trị trái-to-rvalue chuyển đổi ODR-sử dụng được áp dụng].

+0

Cảm ơn. Tôi chắc chắn rằng sự hiểu biết của tôi là chính xác. –

Các vấn đề liên quan