【问题标题】:How to determine between two c++ types without instantiating the types?如何在不实例化类型的情况下确定两种 C++ 类型?
【发布时间】:2012-08-20 09:16:23
【问题描述】:

我有以下问题:

我想在不实际评估“结果”类型的情况下确定两种类型 - 因为该类型可能根本不存在 - 是无效的。 (请不要使用 C++11 的东西)

例子:

 #include <iostream>
 #include <iterator>

template <bool B, typename T, typename F>
struct TemplateIf {
};

template <typename T, typename F>
struct TemplateIf<true, T, F> {
   typedef T Result;
};

template <typename T, typename F>
struct TemplateIf<false, T, F> {
 typedef F Result;
};


int main(int argc, char** argv)
{

// On GCC this is error as std::iterator_traits<int>::value_type doesn't exist 
typename TemplateIf<true, int, std::iterator_traits<int>::value_type >::Result a;
a = 5;

std::cout << a << std::endl;

 return 0;
}

能以某种方式确定吗? (假设选择的类型始终有效,但未选择的类型可能无效)。

【问题讨论】:

  • 我认为您正在寻找的术语是“惰性”评估。此外,这看起来很像我几个小时前问的一个问题。我不知道在一般情况下是否有任何方法可以做到这一点,但在这种特殊情况下,“模板模板”参数可能会起作用。
  • “确定两种类型”是什么意思?
  • @jalf 作为使用 TemplateIf 构造的示例
  • 你到底想在这里做什么?使用 SFINAE 几乎可以肯定是可行的,但是您以错误的方式进行操作。见meta.stackexchange.com/questions/66377/what-is-the-xy-problem
  • 注意 TemplateIf 又名 boost::conditional / C++11 std::conditional。但正如答案所指出的那样,您需要拆分对无效类型的评估,因为在一个地方输入所有 std::iterator_traits&lt;int&gt;::value_type 总是一个问题。

标签: c++ templates metaprogramming


【解决方案1】:

不是直接传递类型,而是传递一个计算类型的元函数。然后可以在 if 中懒惰地评估这个元函数。

#include <iostream>
#include <iterator>

template <bool B, typename T, typename F>
struct TemplateIf {};

template <typename T, typename F>
struct TemplateIf<true, T, F> {
    typedef typename T::type Result;
};

template <typename T, typename F>
struct TemplateIf<false, T, F> {
    typedef typename F::type Result;
};

template <typename T>
struct get_value_type {
    typedef typename std::iterator_traits<T>::value_type type;
};

template <typename T>
struct identity {
    typedef T type;
};

int main(int argc, char** argv)
{
    TemplateIf<true, identity<int>, get_value_type<int> >::Result a;
    a = 5;
    std::cout << a << std::endl;
    return 0;
}

【讨论】:

  • 是的,这行得通。或者只是代替元函数,类作品的部分专业化。
  • typename in main 实际上是错误的,顺便说一句,因为没有依赖名称。
【解决方案2】:

使用惰性求值:

template<class T>
using Apply = typename T::type;

template<class T>
struct identity{ using type = T; };

template<bool B, class T, class F>
struct lazy_if{ using type = Apply<T>; };

template<class T, class F>
struct lazy_if<false, T, F> : lazy_if<true, F, T>{};

template<class T>
struct lazy_iterator_value_type{
  using type = typename std::iterator_traits<T>::value_type;
};

Live example (C++11). 对于 C++03,需要进行简单的重写以消除使用别名,see here

【讨论】:

  • @Kirill:不,看我旁边的评论。只需输入 typename T::type 而不是它。 using type = ... 也是如此,只需改用 typedef ... type;
  • 也许你应用了一点编辑使它成为真正的 C++ 03?
  • @Kirill:嗯,添加了一个 C++03 示例的链接。
猜你喜欢
  • 2016-12-04
  • 2015-10-07
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多