惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
S
SegmentFault 最新的问题
大猫的无限游戏
大猫的无限游戏
The GitHub Blog
The GitHub Blog
M
MIT News - Artificial intelligence
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
Last Week in AI
Last Week in AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
H
Help Net Security
Engineering at Meta
Engineering at Meta
Microsoft Security Blog
Microsoft Security Blog
阮一峰的网络日志
阮一峰的网络日志
J
Java Code Geeks
T
The Blog of Author Tim Ferriss
Hugging Face - Blog
Hugging Face - Blog
C
Check Point Blog
F
Fortinet All Blogs
腾讯CDC
博客园 - Franky
WordPress大学
WordPress大学
U
Unit 42

核桃的炼金工坊

2023 韩国游记 C++23: Flat Containers Deducing This 推し、燃ゆ Customization Point Object 2020 总结 搞了个 C++ 构建系统 软件设计哲学(NOTE) Paxos Note 关于 cpp 可见性的黑魔法后门 一个关于 private member function detect 的 SFINAE 模板 User-defined conversion and Copy elision VIM and Latex Compare Between CRTP and Virtual Interface in C++ Compile Time Reflection in C++11 C++11内存模型 在C++17中的部分新特性 Const Reference of Pointer
Stateful Metaprogramming
Hawtian Wang · 2023-08-01 · via 核桃的炼金工坊

A C++ trick is known as “stateful metaprogramming”, in which one manipulates friend functions and template instantiation to introduce a utilizable state into the compilation.

constexpr bool func() { /* something */ }

constexpr bool a = func();
constexpr bool b = func();
// Think this assertion always fails? With stateful metaprogramming, think again.
static_assert(a != b);

Maybe ill-formed? or UB?

auto flag(auto);

template<bool val>
struct flag_setter {
  friend auto flag(auto) {}
};

int main() {
  flag(1); // 1, error
  flag_setter<true>{};
  flag(1); // 2, ok
}

During the template class flag_setter instantiation, a template class specialization has been added to the global scope. The specialization defines the function flag() (by friend function). So the second invocation success.

auto flag(auto);

template<bool val>
struct flag_setter {
  friend auto flag(auto) {
  }

  bool value = false;
};

template<auto arg = 0, auto condition = requires { flag(arg); }>
consteval auto value() {
  if constexpr (!condition) {
    return flag_setter<condition> {}.value;
  }
  return condition;
}

int main() {
  constexpr auto a = value(); // 1: false
  constexpr auto b = value(); // 2: true
  static_assert(a != b);
}
  • At // 1 the template class flag_setter has not been instantiated. We got false.
  • After the first invocation, the template class flag_setter has been instantiated. The function flag() is defined. We got true.
template<std::size_t N>
struct reader
{
    friend auto counted_flag(reader<N>);
};

template<std::size_t N>
struct setter
{
    friend auto counted_flag(reader<N>) {}
    std::size_t value = N;
};

template<auto N = 0, auto tag = []{}, bool condition = requires(reader<N> red){ counted_flag(red); }>
constexpr auto next()
{
    if constexpr (!condition)
    {
        constexpr setter<N> s;
        return s.value;
    }
    else
    {
        return next<N + 1>();
    }
}

int main()
{
    constexpr auto a = next();
    constexpr auto b = next();
    constexpr auto c = next();
    static_assert(a == 0 && b == 1 && c == 2);
}

  1. Is stateful metaprogramming ill-formed (yet)?
  2. Revisiting Stateful Metaprogramming in C++20
  3. Compiler Explorer