【问题标题】:typedef for function template (partial instantiation)函数模板的 typedef(部分实例化)
【发布时间】:2013-07-19 13:51:50
【问题描述】:

对不起,我真的不知道如何称呼我的问题,希望它适合...

我有一个函数模板,它获取一个参数作为模板参数。对于那个参数,我需要另一个模板参数来声明参数的类型,但是在稍后调用该函数时,我想省略参数的类型。所以,我想要某种 typedef(或其他机制)来摆脱它。

我在其他模板中看到过类似的机制,例如

// given: rule is a template with three arguments
template<typename Attr> using Rule = rule<It, Attr(), Skipper>;

使用std::get的时候不用直接提枚举类也可以相处:

std::get<static_cast<std::size_t>(Enum::type1)>(tuple);

这里是函数,它用于访问带有枚举的元组(比较:https://stackoverflow.com/a/14835597/2524462

template<typename Enum, Enum enum, class ... Types>
typename std::tuple_element<static_cast<std::size_t>(enum), std::tuple<Types...> >::type&
get(std::tuple<Types...>& t) {
  return std::get<static_cast<std::size_t>(enum)>(t);
}

由于它将与多个枚举一起使用,我不想像他那样在模板中硬连线枚举。

它被称为:(1)

std::cout << get<myEnum, myEnum::type1>(tuple);

问题:

  • 我可以使用 typedef 或类似的方式来称呼它吗:

    std::cout << new_get < myEnum::type1 > (tuple);
    
  • 既然它与 std::get 一起工作,那么首先有没有办法拥有一个更智能的模板?

  • 此处的 get 模板将元组类型作为最后一个参数。为什么没有必要在这里拼出它们(1)?编译器如何从给定的参数中找出它们?

我正在使用启用了 C++11 的 gcc 4.8.1。

【问题讨论】:

  • 是否可以使用默认参数?
  • 这个问题可以简化吗?您能简单地说一下您目前拥有(工作)什么以及您希望它如何?
  • 此处所述的模板有效。它被称为(1),我觉得它太冗长了。我想像我第一个问题中所说的那样称呼它。
  • 这是不可能的,原因与此类似:stackoverflow.com/q/11745764/951890
  • @VaughnCato:使用时:“std::get(Enum::type1)>(tuple);”它无需直接拼出枚举即可工作,因此有一种方法...

标签: c++ templates c++11 tuples template-meta-programming


【解决方案1】:

我认为您能做的最好的事情就是为每个枚举创建一个get&lt;&gt;() 函数。这是一个例子:

#include <tuple>
#include <string>
#include <iostream>

typedef std::tuple<std::string,std::string> Tuple1;
typedef std::tuple<std::string,int> Tuple2;

enum class Enum1 {
  name,
  address
};

enum class Enum2 {
  state,
  zip_code
};

template <typename Enum>
constexpr std::size_t indexOf(Enum value)
{
  return static_cast<std::size_t>(value);
}

template <typename Enum,Enum enum_value,typename Tuple>
constexpr auto get(const Tuple &value)
  -> decltype(std::get<indexOf(enum_value)>(value))
{
  return std::get<indexOf(enum_value)>(value);
}

template <Enum1 enum_value>
constexpr auto get(const Tuple1 &value)
  -> decltype(get<Enum1,enum_value>(value))
{
  return get<Enum1,enum_value>(value);
}

template <Enum2 enum_value>
constexpr auto get(const Tuple2 &value)
  -> decltype(get<Enum2,enum_value>(value))
{
  return get<Enum2,enum_value>(value);
}

int main(int,char**)
{
  Tuple1 a("John","123 Foo St");
  Tuple2 b("California",90210);
  std::cerr << get<Enum1::name>(a) << "\n";
  std::cerr << get<Enum1::address>(a) << "\n";
  std::cerr << get<Enum2::state>(b) << "\n";
  std::cerr << get<Enum2::zip_code>(b) << "\n";
}

这很乏味,但这确实有利于在编译时检查枚举是否与元组兼容。

【讨论】:

  • 感谢您的努力。我希望绕过 Enum1 和 Enum2 的显式实例化。我仍然不明白的是,为什么 template constexpr auto get(Enum enum_value, const Tuple &value) -> decltype(std::get(value)) 是不可能的(在函数体外使用参数“枚举值”)但模板 auto add(T t, U u) -> decltype(t + u);没问题。
  • @MikeM:在template &lt;class T,class U&gt; auto add(T t,U u) -&gt; decltype(t+u) 的情况下,函数的返回类型仅取决于参数的类型,这些类型在编译时是已知的。在template &lt;typename Enum,typename Tuple&gt; constexpr auto get(Enum enum_value,const Tuple &amp;value) -&gt; decltype(std::get&lt;indexOf(enum_value)&gt;(value)) 的情况下,返回类型取决于参数的值,这在编译时是未知的(通常)。
  • 非常感谢。现在我看到了区别。那么,是否需要类似 constexpr 之类的参数?我正试图对基本规则有所了解。我刚刚发现,虽然您的 indexOf 工作正常,但这不起作用 template&lt;typename Enum&gt; struct Test{Test(Enum value) {...}} 并称它为 Test(myEnum::type1); 好吧,仍在学习。感谢您的努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多