【问题标题】:How to write code to do conditional template instantiation in C++如何编写代码以在 C++ 中进行条件模板实例化
【发布时间】:2018-08-30 21:49:17
【问题描述】:

我正在编写一个在 size_t 上参数化的类模板,

template<size_t k>
class MyClass {...}

参数 k 应该小于 10,在这种情况下,我希望它超过这个值就编译失败。如何在 C++11 及更高版本中做到这一点?

MyClass<1> instance1; // ok
MyClass<2> instance2; // ok
MyClass<100> instance100; // fail to compile

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    使用static_assert

    template<size_t k>
    class MyClass {
        static_assert(k < 10, "Illegal k");
    };
    
    int main() {
      MyClass<50> t; //< Compile time failure
    }
    

    【讨论】:

    • 您也可以将static_assert 放入类主体中。以您的方式,只有 ctor 调用将无法编译,这可能是也可能不是 OP 想要的。
    • 已更新。解决方案。是的,你是对的,我可以将static_assert 放在课堂上的任何位置。
    • 我投票支持这个答案。虽然我发现 SFINAE(例如 std::enable_if)使用起来非常有趣,但它的可读性较差,并且编译时错误不像 static_assert 那样清晰。
    【解决方案2】:

    您可以在模板参数中添加一个检查,例如

    template<size_t k, std::enable_if_t<k <= 10, bool> = true>
    class MyClass {};
    

    这将允许MyClass&lt;1&gt; instance1;MyClass&lt;100&gt; instance100; 将无法编译。

    【讨论】:

    • 我很好奇为什么有人会使用这种技术;在我看来,cplusplusrat 的static_assert() 技术比这种技术更简单易懂。另外我不熟悉std::enable_if_t&lt;&gt;,你能解释一下这是如何完成OP需要的吗?导致MyClass&lt;100&gt;编译失败怎么办?
    • @phonetagger 如果你正在做一些更复杂的元编程,enable_if 会给你更多的机会。例如。为某些模板参数启用某些函数重载和为其他模板参数启用其他一些重载是很常见的。但在这个特殊的用例中,正如你所说,我认为没有理由比 static_assert 更喜欢它。
    • @L.F.我已更新答案以使用bool。我一直在努力解决答案,但错过了这个。
    • @NathanOliver 没关系,这一直被忽视,没有编译器真正诊断出这个。
    • @L.F.不,他们没有。我从一些人那里听说一些编译器会出错,但主要的编译器不会出错,我想这是一件好事,因为有很多资源可以通过void* 方式来实现。 FWIW 我使用enable_if_t&lt;..., boo&gt; = true 的所有新代码来验证代码的合规性。不会再重要了,但我喜欢看到true,因为它提醒我只有在条件为真时才启用。
    【解决方案3】:

    如果你使用 C++11,你可以使用std::enable_if

    template<std::size_t k, typename unused = typename std::enable_if<k <= 10>::type>
    class MyClass {};
    

    如果您能够使用 C++14 或更高版本,则可以使用 std::enable_if_t

    template<std::size_t k, typename unused = std::enable_if_t<k <= 10 >>
    class MyClass {};
    

    【讨论】:

    • 我很好奇为什么有人会使用这些技术;在我看来,cplusplusrat 的static_assert() 技术比这些技术中的任何一个都更简单易懂。另外我不熟悉std::enable_if&lt;&gt;std::enable_if_t&lt;&gt;,你能解释一下这些是如何完成OP 需要的吗?
    • 您必须在 C++ 中查找 SFINAE。这是一个起始页:en.cppreference.com/w/cpp/language/sfinae.
    • 弄清楚 SFINAE 和 std::enable_if&lt;&gt;std::enable_if_t&lt;&gt; 是如何工作的已经够难的了;即使您省略了细节,添加几句话来解释如何完成 OP 所需的本质仍然会有所帮助。如果斯科特·迈耶斯没有以读者可以理解的方式写作,他的书就永远不会超过几本书。 SO 不应该成为已经是语言专家的人的技术参考站点;它应该比这更有帮助。
    • @phonetagger 不幸的是,SFINAE 通常被认为是 C++ 的一个非常基本的部分,预计将在入门书中介绍。
    • 另外,一个(过度)聪明的用户可以通过显式提供第二个参数来劫持这个解决方案。
    猜你喜欢
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    相关资源
    最近更新 更多