草庐IT

c++ - 编译时模板实例化检查

coder 2023-11-13 原文

是否可以在编译时检查模板类型是否已实例化,以便我可以在 enable_if 特化中使用此信息?

假设我有

template <typename T> struct known_type { };

如果 known_type 在编译时被实例化,我能否以某种方式定义其值为 true 的 is_known_type ?

最佳答案

如果您利用在 constexpr 的地方可能会或可能不会使用特定表达式这一事实,就可以做到这一点。 s 是预期的,您可以查询以查看您拥有的每个候选人的状态。特别是在我们的案例中,constexpr没有定义的 s 不能作为常量表达式和 noexcept 传递是常量表达式的保证。因此,noexcept(...)返回 true表示存在正确定义的 constexpr .

本质上,这对待 constexpr s 作为是/否开关,并在编译时引入状态。

请注意,这几乎是一个 hack,您将需要针对特定​​编译器的解决方法(请参阅前面的文章)和这个特定的 friend基于 -based 的实现可能会被标准的 future 修订视为格式错误。

有了这个……

用户 Filip Roséenhis article 中提出了这个概念专门致力于它。

他的示例实现是,引用了解释:

constexpr int flag (int);

A constexpr function can be in either one of two states; either it is usable in a constant-expression, or it isn't - if it lacks a definition it automatically falls in the latter category - there is no other state (unless we consider undefined behavior).

Normally, constexpr functions should be treated exactly as what they are; functions, but we can also think of them as individual handles to "variables" having a type similar to bool, where each "variable" can have one of two values; usable or not-usable.

In our program it helps if you consider flag to be just that; a handle (not a function). The reason is that we will never actually call flag in an evaluated context, we are only interested in its current state.

template<class Tag>
struct writer {
  friend constexpr int flag (Tag) {
    return 0;
  }
};

writer is a class template which, upon instantiation, will create a definition for a function in its surrounding namespace (having the signature int flag (Tag), where Tag is a template-parameter).

If we, once again, think of constexpr functions as handles to some variable, we can treat an instantiation of writer as an unconditional write of the value usable to the variable behind the function in the friend-declaration.

template<bool B, class Tag = int>
struct dependent_writer : writer<Tag> { };

I would not be surprised if you think dependent_writer looks like a rather pointless indirection; why not directly instantiate writer where we want to use it, instead of going through dependent_writer?

  1. Instantiation of writer must depend on something to prevent immediate instantiation, and;
  2. dependent_writer is used in a context where a value of type bool can be used as dependency.
template<
  bool B = noexcept (flag (0)),
  int    =   sizeof (dependent_writer<B>)
>
constexpr int f () {
  return B;
}

The above might look a little weird, but it's really quite simple;

  1. will set B = true if flag(0) is a constant-expression, otherwise B = false, and;
  2. implicitly instantiates dependent_writer (sizeof requires a completely-defined type).

The behavior can be expressed with the following pseudo-code:

IF [ `int flag (int)` has not yet been defined ]:
  SET `B` =   `false`
  INSTANTIATE `dependent_writer<false>`
  RETURN      `false`
ELSE:
  SET `B` =   `true`
  INSTANTIATE `dependent_writer<true>`
  RETURN      `true`

最后,概念验证:

int main () {
  constexpr int a = f ();
  constexpr int b = f ();
  static_assert (a != b, "fail");
}

我将此应用于您的特定问题。这个想法是使用 constexpr是/否切换以指示类型是否已实例化。因此,对于您拥有的每种类型,您都需要一个单独的开关。

template<typename T>
struct inst_check_wrapper
{
    friend constexpr int inst_flag(inst_check_wrapper<T>);
};

inst_check_wrapper<T>本质上为您可能提供的任何类型包装一个开关。它只是原始示例的通用版本。

template<typename T>
struct writer 
{
    friend constexpr int inst_flag(inst_check_wrapper<T>) 
    {
        return 0;
    }
};

开关切换器与原始示例中的相同。它提出了您使用的某种类型的开关的定义。为了便于检查,添加一个辅助开关检查器:

template <typename T, bool B = noexcept(inst_flag(inst_check_wrapper<T>()))>
constexpr bool is_instantiated()
{
    return B;
}

最后,类型将自身“注册”为已初始化。就我而言:

template <typename T>
struct MyStruct
{
    template <typename T1 = T, int = sizeof(writer<MyStruct<T1>>)>
    MyStruct()
    {}
};

一旦请求特定的构造函数,开关就会打开。示例:

int main () 
{
    static_assert(!is_instantiated<MyStruct<int>>(), "failure");
    MyStruct<int> a;
    static_assert(is_instantiated<MyStruct<int>>(), "failure");
}

Live on Coliru.

关于c++ - 编译时模板实例化检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28179835/

有关c++ - 编译时模板实例化检查的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  4. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  5. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  6. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  7. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  8. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  9. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  10. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

随机推荐