c++ - 为什么未使用的成员模板函数的类模板实例化失败

标签 c++ templates

这有什么问题:

#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成员模板函数只有在真正使用时才检查吗?

<小时/>

编辑:
正如评论中提到的,我在上面的代码中犯了一个无意的错误:std::enable_if应该是std::enable_if_t ,如在这个更正后的 Playground 中:https://godbolt.org/z/cyuB3d

这改变了编译器传递此代码而没有错误的情况:

  • gcc:失败
  • clang:失败
  • x64 msvc v19.22:编译
  • x64 msvc v19.23(内部测试):失败

但是,问题仍然存在:为什么从未使用过的函数的默认模板参数会导致编译失败?

最佳答案

原因是 std::is_constructible 需要完整的类型:( Table 42 )

Template

template <class T>
struct is_­copy_­constructible;

Preconditions

T shall be a complete type, cv void, or an array of unknown bound.

未能满足库“应”的要求会导致未定义的行为。

关于c++ - 为什么未使用的成员模板函数的类模板实例化失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58320421/

相关文章:

c++ - 在另一个命名空间中定义一个符号

c++ - 结束并刷新缓冲区

c++ - 程序的退出状态

c++ - 这个递归函数的时间复杂度是多少?

c++ - 如何传递具有可变参数的成员函数作为模板参数?

c++ - 为类模板忽略了用户定义的转换运算符(对于非模板则不然)

c++ - 使用 STL 算法缓存复杂的比较函数?

c++ - Qt C++ MySQL 到 QTableView 多个连接表为空

C++ 模板化映射包含自身

c++ - 在模板中使用 friend