有状态元编程中使用的模板函数/类隐式实例化规则

时间:2017-01-11 13:14:00

标签: c++ c++11 c++14 template-meta-programming

我正在使用有关有状态元编程的代码示例。 可以从以下链接找到原始代码示例:http://b.atch.se/posts/non-constant-constant-expressions/#appendix-clang-workaround

为了理解这种技术,我尝试每次修改代码示例。以下是最新版本仍然有效:

Command

对我来说,用int替换Tag似乎微不足道。但实际上,这种替换会产生constexpr int adl_flag(int); template <class Tag> struct writer { friend constexpr int adl_flag(int) { return 0; } }; template <int = adl_flag(0)> constexpr bool is_flag_usable(int) { return true; } constexpr bool is_flag_usable (...) { return false; } template < class Tag = int, bool B = is_flag_usable(0), int = sizeof (writer<Tag>) // replace Tag with int > constexpr int f() { return B; } int main() { constexpr int a = f(); constexpr int b = f(); static_assert(a != b, "fail"); return 0; }

我想这是因为编译器不再为第二次调用隐式实例化f:

static_assert fail

但模板类型参数Tag似乎与此无关。请问有人能解释一下这里到底发生了什么。

我使用的编译器是constexpr int b = f(); 。使用g++ 5.4.1进行编译。

1 个答案:

答案 0 :(得分:3)

sizeof(writer<int>)不依赖。这意味着在第一阶段查找中找到wrapper<int>,解析f时(一次)。

另一方面,

sizeof(writer<Tag>)依赖于Tag。因此,它的查找推迟到第二阶段,当f被实例化时(在每个呼叫站点)。