C++:为什么编译器在不使用时实例化模板

标签 c++ templates arguments instantiation

让我们考虑这段代码:

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>'

但是我没有使用模板方法f(int)当参数 <bool c>false那么它不应该存在。

最佳答案

编译器不会像您错误地相信的那样“实例化”您的模板。编译器只是试图解析和分析您的模板声明,它是您的类定义的一部分。如果类被实例化,则所有成员声明 都必须有效。您的成员模板声明无效。因此错误。

如果某个模板“未使用”,则意味着它没有得到专门化和实例化。但是该模板的声明 仍然必须有效。并且立即检查声明中那些不依赖于模板参数的部分的有效性。换句话说,你在代码中写的和

template <typename T = jksgdcaufgdug> void foo() {}

int main() {}

或者,更接近你的情况

template <typename T = std::enable_if<false>::type> void foo() {}

int main() {}

即使这些程序不“使用”(不实例化)功能模板foo , 它仍然不意味着 foo 的声明可以包含随机垃圾,如 jksgdcaufgdug或明确引用不存在的实体,如 std::enable_if<false>::type .由于这个原因,上述示例将无法编译。

您可以在相关 上下文中使用“随机垃圾”,例如

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()
{ 
}

它不会产生“早期”错误,但在您的情况下 enable_if<c>不依赖于 Temp ,所以它不在依赖上下文中。这意味着 typename enable_if<c>::type 的正确性当您实例化 A<false> 时立即检查.

关于C++:为什么编译器在不使用时实例化模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31172835/

相关文章:

C++ - 获取派生类型作为模板参数

wpf - 在WPF中,如何在TextBox中显示验证错误,如下图所示?

javascript - 带有对象数组的 mustache 模板

c - 二维数组转化为指针

python-3.x - 如何将参数传递给其他函数(通常通过 scipy)?

android - ndk-gdb 无法找到 gdb.setup

c++ - 如何在64位x86环境下编译32位x86应用程序?

python - argparse - 每个操作不同的强制/可用参数

c++ - omp 缩减和 lambda 函数

C++ - 如何有效地找出 vector 中的任何字符串是否可以从一组字母中组装出来