草庐IT

C++ 根据其他模板参数推导模板参数

coder 2024-02-01 原文

假设我有以下类(class):

template <class T, class U, class V> Foo
{
    ...
};

模板参数具有不同的映射,因此我可以根据 T 是什么推导出其他模板参数 U 和 V。例如,如果 T 是 double,则 U 和 V 将始终是某些类 D1 和 D2,如果 T 是 float,则 U 和 V 将始终是其他类 F1 和 F2。

考虑到这一点,有没有一种方法可以只传入一个模板参数,并让编译器推导出其他两个参数?

我知道简单的答案是让这些其他类也模板化并将模板参数 T 传递给它们,但我无法使这些类模板化(它们是由工具自动生成的)。

理想情况下,我可以像这样使用 typedef 或 #define:

typedef Foo<double> Foo<double, D1, D2>
typedef Foo<float> Foo<float, F1, F2>

但是这些不编译。我想知道是否有一种方法可以使用模板元编程或模板模板参数来解决这个问题,但我似乎无法理解这些概念,我有一种直觉,可能有一个更简单的答案。有人有什么想法吗?

最佳答案

Angew 给出的答案向您展示了正确的方法,但没有向您展示如何应对无法推导出 UV必须推导的情况 由实例化客户端提供。

要处理这种情况,您可以为模板参数 UV 分配默认参数:

struct D1 { }; struct D2 { };
struct F1 { }; struct F2 { };

// Primary template
template<typename T>
struct deduce_from
{
};

// Specialization for double: U -> D1, V -> D2
template<>
struct deduce_from<double>
{
    typedef D1 U;
    typedef D2 V;
};

// Specialization for float: U -> F1, V -> F2
template<>
struct deduce_from<float>
{
    typedef F1 U;
    typedef F2 V;
};

// Give defaults to U and V: if deduce_from is not specialized for
// the supplied T, and U or V are not explicitly provided, a compilation
// error will occur 
template<
    typename T,
    typename U = typename deduce_from<T>::U,
    typename V = typename deduce_from<T>::V
    >
struct Foo
{
    typedef U typeU;
    typedef V typeV;
};

下面是一个简单的程序来测试上述解决方案的正确性:

#include <type_traits>

int main()
{
    static_assert(std::is_same<Foo<double>::typeU, D1>::value, "Error!");
    static_assert(std::is_same<Foo<double>::typeV, D2>::value, "Error!");
    static_assert(std::is_same<Foo<float>::typeU, F1>::value, "Error!");
    static_assert(std::is_same<Foo<float>::typeV, F2>::value, "Error!");

    // Uncommenting this will give you an ERROR! 
    // No deduced types for U and V when T is int
    /* static_assert(
        std::is_same<Foo<int>::typeU, void>::value, "Error!"
        ); */
    static_assert(
        std::is_same<Foo<int, bool, char>::typeU, bool>::value, "Error!"
        ); // OK
    static_assert(
        std::is_same<Foo<int, bool, char>::typeV, char>::value, "Error!"
        ); // OK
}

关于C++ 根据其他模板参数推导模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15025704/

有关C++ 根据其他模板参数推导模板参数的更多相关文章

  1. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

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

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

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

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

  6. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  7. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

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

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

  9. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  10. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

随机推荐