C++:为什么编译器在不使用时实例化模板
C++: Why does the compiler instantiate a template when it is not used
让我们考虑一下这段代码:
template <bool c>
class A {
public:
A() = default;
// I want to enable f(int) only if c == true
template<typename Temp = typename enable_if<c>::type>
void f(int val) {
cout << val << endl;
};
};
int main() {
A<false> a;
A<true> b;
b.f(543);
}
当我尝试编译它时,出现以下错误:
error: no type named 'type' in 'struct std::enable_if<false, void>'
但是当参数 <bool c>
是 false
时我不使用模板方法 f(int)
那么它不应该存在。
编译器没有 "instantiate" 您的模板,您似乎错误地认为。编译器只是试图解析和分析您的模板声明,它是您 class 定义的一部分。如果 class 被实例化,那么所有成员 声明 都必须有效。您的成员模板声明无效。因此错误。
如果某个模板是"not used",这意味着它没有得到专门化和实例化。但是该模板的 声明 仍然必须有效。并且立即检查 不依赖于模板参数 的那部分声明的有效性。换句话说,你在代码中写的和
没有区别
template <typename T = jksgdcaufgdug> void foo() {}
int main() {}
或者,更接近你的情况
template <typename T = std::enable_if<false>::type> void foo() {}
int main() {}
即使这些程序没有"use"(不实例化)函数模板foo
,这仍然不意味着foo
的声明可以包含像[=这样的随机垃圾16=] 或明确引用不存在的实体,如 std::enable_if<false>::type
。由于这个原因,上述示例将无法编译。
您可以在 dependent 上下文中使用 "random garbage",例如
template <typename T> void foo(typename T::kjhdfjskhf x)
{
typename T::jksgdcaufgdug i;
}
并且您可以在依赖上下文中使用 std::enable_if
,例如
template <typename T,
typename U = typename enable_if<is_void<T>::value>::type>
void bar()
{
}
并且它不会产生 "early" 错误,但在您的情况下 enable_if<c>
不依赖于 Temp
,因此它不在依赖上下文中。这意味着当您实例化 A<false>
.
时会立即检查 typename enable_if<c>::type
的正确性
让我们考虑一下这段代码:
template <bool c>
class A {
public:
A() = default;
// I want to enable f(int) only if c == true
template<typename Temp = typename enable_if<c>::type>
void f(int val) {
cout << val << endl;
};
};
int main() {
A<false> a;
A<true> b;
b.f(543);
}
当我尝试编译它时,出现以下错误:
error: no type named 'type' in 'struct std::enable_if<false, void>'
但是当参数 <bool c>
是 false
时我不使用模板方法 f(int)
那么它不应该存在。
编译器没有 "instantiate" 您的模板,您似乎错误地认为。编译器只是试图解析和分析您的模板声明,它是您 class 定义的一部分。如果 class 被实例化,那么所有成员 声明 都必须有效。您的成员模板声明无效。因此错误。
如果某个模板是"not used",这意味着它没有得到专门化和实例化。但是该模板的 声明 仍然必须有效。并且立即检查 不依赖于模板参数 的那部分声明的有效性。换句话说,你在代码中写的和
没有区别template <typename T = jksgdcaufgdug> void foo() {}
int main() {}
或者,更接近你的情况
template <typename T = std::enable_if<false>::type> void foo() {}
int main() {}
即使这些程序没有"use"(不实例化)函数模板foo
,这仍然不意味着foo
的声明可以包含像[=这样的随机垃圾16=] 或明确引用不存在的实体,如 std::enable_if<false>::type
。由于这个原因,上述示例将无法编译。
您可以在 dependent 上下文中使用 "random garbage",例如
template <typename T> void foo(typename T::kjhdfjskhf x)
{
typename T::jksgdcaufgdug i;
}
并且您可以在依赖上下文中使用 std::enable_if
,例如
template <typename T,
typename U = typename enable_if<is_void<T>::value>::type>
void bar()
{
}
并且它不会产生 "early" 错误,但在您的情况下 enable_if<c>
不依赖于 Temp
,因此它不在依赖上下文中。这意味着当您实例化 A<false>
.
typename enable_if<c>::type
的正确性