C++ 在模板SFINAE约束中使用间接级别会导致硬错误
在下面的代码中() 当我删除此()约束中带有C++ 在模板SFINAE约束中使用间接级别会导致硬错误,c++,templates,language-lawyer,c++17,sfinae,C++,Templates,Language Lawyer,C++17,Sfinae,在下面的代码中() 当我删除此()约束中带有Identity的间接寻址时,错误就会消失 模板< 类型名T, typename U=std::衰变, std::如果启用,则启用< std::is_constructible::value>*=nullptr> 显式某物(T&{}; 根据我的理解,这里的问题是我们试图实例化std::is_constructible,然后实例化某物的构造函数,然后再实例化std::is_constructible,依此类推 但是,当我尝试在没有Identity的情况
Identity
的间接寻址时,错误就会消失
模板<
类型名T,
typename U=std::衰变,
std::如果启用,则启用<
std::is_constructible::value>*=nullptr>
显式某物(T&{};
根据我的理解,这里的问题是我们试图实例化std::is_constructible
,然后实例化某物的构造函数,然后再实例化std::is_constructible
,依此类推
但是,当我尝试在没有Identity
的情况下编译此文件时,为什么错误会消失呢?当我使用Identity
时,为什么会出错?您已经知道存在一个“递归实例化”。没有真正的递归;在“有效”的情况下发生的情况很简单,当考虑构造函数模板以确定从const Something&
进行的构造是否会成功时,std::is_constructible
没有成员值
。(与普遍的看法相反,类C
不需要完整才能使用C:::
命名成员-但是命名成员必须已经声明,并且“已经”的确切含义是。)
该错误位于构造函数模板的即时上下文中,因此该模板将被静默忽略。(在这种情况下,这没有什么区别:(已删除的)复制构造函数更匹配,因为它不是模板。)这确定了缺失的值是false
,这至少与第一次拒绝构造函数模板的情况一致。这可能违反了std::is_constructible
本身的专门化;如果我们否定了<代码> Enable中的条件,如果< /COD>控制它自己,那么Helistic就随之而来。
您的Identity
遇到相同的错误(或者相关专业化尚未完成的更普遍的问题)。作为辅助实例化的一部分,错误是不可恢复的。是可构造的。\u v
是从C++17开始的,只是为了简化我头脑中的代码:std::is_constructible
不是从它的任何一个参数继承的,因此它在不同于您的标识类的约束下运行。这是否也意味着[meta.unary.prop]/表47,关于std::is_constructible
模板参数的完整性先决条件,违反了“T
和参数包Args
中的所有类型都应为完整类型”(在两个示例中)?@dfri:No默认模板参数直到需要时才会实例化,当某个东西
很长时间完成时。我不确定是否会这样做,如果我不从它继承并直接使用值成员,那么为什么错误仍然存在?@好奇:我过分强调了完整性问题,对不起。值
的查找同样失败由于继承while是可构造的
正在被实例化,并且同样超出了直接上下文。我添加了更多解释性细节,并将重新措辞以避免对完整性的混淆。
#include <type_traits>
template <typename T>
struct Identity : public T {};
class Something {
public:
Something() = default;
Something(const Something&) = delete;
Something(Something&&) = default;
Something& operator=(const Something&) = default;
Something& operator=(Something&&) = default;
template <
typename T,
typename U = std::decay_t<T>,
std::enable_if_t<Identity<
std::is_constructible<U, T&&>>::value>* = nullptr>
explicit Something(T&&) {};
};
int main() {
static_cast<void>(std::is_constructible<Something, const Something&>{});
}
error: base class has incomplete type
struct Identity : public T {};
~~~~~~~^
template <
typename T,
typename U = std::decay_t<T>,
std::enable_if_t<
std::is_constructible<U, T&&>::value>* = nullptr>
explicit Something(T&&) {};