模板元编程完全可以在C++20中被替换吗



尽管模板元编程的想法——尽可能在编译时计算一些东西——非常棒,但我想知道当前的C++20功能是否允许我们通过使用constexprconstevalif constexprconcept和其他C++20功能来完全避免TMP。这是真的吗?或者TMP提供的某些功能无法替代?

,模板元编程不能被C++20语言实用程序完全取代;尽管大量可以。

constexprconsteval等当然都有助于减轻传统上使用TMP所做的事情的负担(多年来情况越来越多(,但模板仍然可以用于类型确定的正交目的,更重要的是,还可以用于类型生成

constexpr/consteval/等在它们的表达性方面是有限的,因为这些函数的参数本身不是常数表达式。即使在consteval函数中也是如此,尽管它只能在编译时运行。这意味着以下是不合法的C++:

template <typename T>
consteval auto make_array(std::size_t n) { 
return std::array<T,n>{}; 
//                  ^ - error, 'n' is not a constant expression
}

实时示例

这种限制意味着更复杂的生成仍然需要传统的模板元编程技术。这在试图产生变异扩张时尤其必要。

(如注释中所述,这也会阻止在解析字符串时生成适当的类型(

举个例子,考虑一下如果不使用内部函数,std::index_sequence的实现会是什么样子。扩展为index_sequence<0, 1, 2, ..., N-1>make_index_sequence<N>的天真实现看起来像这样:

template <std::size_t... Ints>
struct index_sequence 
{
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};

namespace detail {
template <bool End, std::size_t N, std::size_t...Tails>
struct make_index_sequence_impl
: make_index_sequence_impl<((N-1) == 0u), N-1, N-1, Tails...>{};
template <std::size_t N, std::size_t...Tails>
struct make_index_sequence_impl<true, N, Tails...>
: std::type_identity<index_sequence<Tails...>>{};
} // namespace detail
template <std::size_t N>
using make_index_sequence = typename detail::make_index_sequence_impl<(N==0u), N>::type;

实时示例

技术上index_sequence示例可以用C++20编写,使用递归consteval函数返回index_sequence的实例,但这只是因为我们可以将值传递给模板推导的函数。更复杂的类型示例在编译时不会有这种奢侈。

通常,像这样更复杂的类型生成将需要一些级别的TMP,特别是如果类型对默认可构造性有限制,或者它本身不能是常量表达式。在这种情况下,这将需要部分模板专业化,这些专业化开始属于一般的模板元编程实践。

最新更新