在C++;编译时 我们今天讨论了“FiZZ嗡嗡”编程测试,我想用C++实现,但是用元编程。理想情况下,它将在编译期间生成输出
我当前的代码使用模板,但为了生成输出,仍然必须执行模板。在电视上看在C++;编译时 我们今天讨论了“FiZZ嗡嗡”编程测试,我想用C++实现,但是用元编程。理想情况下,它将在编译期间生成输出,c++,gcc,fizzbuzz,C++,Gcc,Fizzbuzz,我当前的代码使用模板,但为了生成输出,仍然必须执行模板。在电视上看 我仍然使用std::cout,虽然通过一些模板技巧可以在编译时生成字符串,但在编译时打印它似乎不合理 下面是生成字符串的代码: #include <iostream> #include <type_traits> #include <utility> // Compile time string template <char ...C> struct str_lit {
我仍然使用
std::cout,虽然通过一些模板技巧可以在编译时生成字符串,但在编译时打印它似乎不合理
下面是生成字符串的代码:
#include <iostream>
#include <type_traits>
#include <utility>
// Compile time string
template <char ...C> struct str_lit
{
static constexpr char value[] {C..., '\0'};
};
// Integer to str_lit
constexpr std::size_t cexpr_pow(std::size_t x, std::size_t y)
{
std::size_t ret = 1;
while (y--)
ret *= x;
return ret;
}
template <std::size_t N, std::size_t X, typename = std::make_index_sequence<X>> struct num_to_sl_impl;
template <std::size_t N, std::size_t X, std::size_t ...Seq> struct num_to_sl_impl<N, X, std::index_sequence<Seq...>>
{
static constexpr auto func()
{
if constexpr (N >= cexpr_pow(10,X))
return num_to_sl_impl<N, X+1>::func();
else
return str_lit<(N / cexpr_pow(10,X-1-Seq) % 10 + '0')...>{};
}
};
template <std::size_t N> using num_to_sl = decltype(num_to_sl_impl<N,1>::func());
// str_lit concatenation
template <typename F, typename ...P> struct sl_cat_impl {using type = typename sl_cat_impl<F, typename sl_cat_impl<P...>::type>::type;};
template <char ...C1, char ...C2> struct sl_cat_impl<str_lit<C1...>,str_lit<C2...>> {using type = str_lit<C1..., C2...>;};
template <typename F, typename ...P> using sl_cat = typename sl_cat_impl<F, P...>::type;
// The FizzBuzz
template <std::size_t N> struct fizzbuzz_impl
{
using fizz = std::conditional_t<N % 3 == 0,
str_lit<'f','i','z','z'>,
str_lit<>>;
using buzz = std::conditional_t<N % 5 == 0,
str_lit<'b','u','z','z'>,
str_lit<>>;
using type = sl_cat<typename fizzbuzz_impl<N-1>::type,
std::conditional_t<N % 3 == 0 || N % 5 == 0,
sl_cat<fizz, buzz>,
num_to_sl<N>>,
str_lit<'\n'>>;
};
template <> struct fizzbuzz_impl<0>
{
using type = str_lit<>;
};
template <std::size_t N> using fizzbuzz = typename fizzbuzz_impl<N>::type;
#包括
#包括
#包括
//编译时字符串
模板结构
{
静态constexpr字符值[]{C..,'\0'};
};
//整数到str_lit
constexpr std::size\u t cexpr\u pow(std::size\u t x,std::size\u t y)
{
标准:尺寸=1;
而(y--)
ret*=x;
返回ret;
}
模板结构num_to_sl_impl;
模板结构num_to_sl_impl
{
静态constexpr auto func()
{
如果constexpr(N>=cexpr_pow(10,X))
将num_返回到_sl_impl::func();
其他的
返回str_lit{};
}
};
使用num_to_sl=decltype(num_to_sl_impl::func())的模板;
//str_-lit级联
模板结构sl_cat_impl{using type=typename sl_cat_impl::type;};
模板结构sl_cat_impl{using type=str_lit;};
使用sl_cat=typename sl_cat_impl::type的模板;
//嘶嘶作响
模板结构fizzbuzz_impl
{
使用fizz=std::conditional\u t;
使用buzz=std::conditional\u t;
使用类型=sl_cat;
};
模板结构fizzbuzz_impl
{
使用类型=str_lit;
};
使用fizzbuzz=typename fizzbuzz_impl::type的模板;
用法示例:
int main()
{
std::cout << fizzbuzz<15>::value;
}
intmain()
{
std::难道您不能在编译时以平台无关的方式打印(但),但是,您可能感兴趣的是,编译时计算的要点不是在编译时输出结果。它是在编译时生成结果,以便使用(例如:输出)在运行时它将使用常量。但是,我想,如果你真的想,你可能会编写一些复杂的模板魔术,在编译时将结果作为编译器错误消息的一部分打印出来——虽然这很愚蠢。好吧,如果你能构建一个字符串,你可以在代码的末尾触发一个静态断言
它将字符串显示为错误。一致性编译器不需要为格式良好的程序发出任何诊断信息,因此无法使用格式良好的程序回答您的问题。您最好创建一条包含结果的错误消息(例如,作为错误构造的模板参数或数组大小,或者作为静态断言)。当然,对格式错误的程序的任何诊断也是未指定的,因此编译器可能只会说“boo”。
int main()
{
std::cout << fizzbuzz<15>::value;
}