簡體   English   中英

為什么未使用的成員模板 function 的 class 模板實例化失敗

[英]Why class template instantiation fails for unused member template function

這有什么問題:

#include <type_traits>

struct A;

template<typename T>
struct B
{
    template<typename=std::enable_if<std::is_copy_constructible<T>::value>>
    void f1() {}
};

template<typename T>
struct C {};


// Type your code here, or load an example.
int main() {
    // Following fails
    B<A> b;
    // Could use this:
    // b.f1<C>();

    // This complies
    C<A> c;

    return 0;
}

/* This to be in or not doesn't make a difference
struct A
{};
*/

我在這里試過這個: https://godbolt.org/z/NkL44s使用不同的編譯器:

  • x86-64 gcc 9.2:編譯
  • x86-64 gcc(主干):失敗
  • x86-64 clang 6.0.0:編譯
  • x86-64 clang 7.0.0 及更高版本:失敗
  • x64 msvc v19.22:編譯
  • x64 msvc v19.23(內部測試):失敗

那么為什么最近的編譯器會拒絕這個呢? 在實例化B<A>時,不清楚f1將以哪種形式使用,或者是否會使用它。 那么為什么編譯器會抱怨呢? f1成員模板function不應該只有在真的使用時才檢查?


編輯
正如評論中提到的,我在上面的代碼中犯了一個無意的錯誤: std::enable_if應該是std::enable_if_t ,就像在這個更正的游樂場中一樣: https://godbolt.org/z/cyuB3d

這改變了編譯器無錯誤地傳遞此代碼的情況:

  • gcc:失敗
  • clang:失敗
  • x64 msvc v19.22:編譯
  • x64 msvc v19.23(內部測試):失敗

但是,問題仍然存在:為什么從未使用過的 function 的默認模板參數會導致編譯失敗?

原因是std::is_constructible需要一個完整的類型:( 表 42

模板

template <class T> struct is_copy_constructible;

前提條件

T應為完整類型、 cv void 或未知邊界數組。

未能滿足庫“應”要求會導致未定義的行為。

is_copy_constructible<T>上的cppreference

T 應該是一個完整的類型,(可能是 cv 限定的)void,或者一個未知邊界的數組。 否則,行為未定義。

因此,您似乎在較舊的編譯器版本中只有普通的 UB,而較新的編譯器版本足以告訴您A必須是完整的類型。

請注意,在存在 UB 的情況下,編譯器不需要發出錯誤,但他們可能會這樣做,這是一件好事。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM