【问题标题】:Template Type != Deduced type模板类型!=推导类型
【发布时间】:2017-08-16 22:52:50
【问题描述】:

我试图给一个类型一个友好的名字作为模板类型名,因为我需要在函数的几个地方使用这个名字。类型是根据参数包中其他模板参数的个数来推断的,如下所示:

#include <cassert>
#include <functional>
#include <type_traits>

template < typename ... TArgs, typename Functor = std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > > >
void DoStuff(const Functor & func, TArgs ... args) {
    if constexpr (sizeof...(TArgs) == 0)
        assert(typeid(Functor).hash_code() == typeid(std::function<int ()>).hash_code());
    else
        assert(typeid(Functor).hash_code() == typeid(std::function<int (TArgs...)>).hash_code());
}

int main(int argc, char * argv[]) {
    DoStuff([] () { return 5; });
    DoStuff([] (int a) { return a; });

    return 0;
}

这编译得很好,但是两个断言都失败了,因为别名 Functor 实际上不是 std::function&lt;&gt;。另一方面,如果我更改代码以在 typeid 调用中重复 Functor 的定义,它会完美运行,如下所示:

#include <cassert>
#include <functional>
#include <type_traits>

template < typename ... TArgs, typename Functor = std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > > >
void DoStuff(const Functor & func, TArgs ... args) {
    if constexpr (sizeof...(TArgs) == 0)
        assert(typeid(std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > >).hash_code() == typeid(std::function<int ()>).hash_code());
    else
        assert(typeid(std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > >).hash_code() == typeid(std::function<int (TArgs...)>).hash_code());
}

int main(int argc, char * argv[]) {
    DoStuff([] () { return 5; });
    DoStuff([] (int a) { return a; });

    return 0;
}

为什么第一个声明(使用typname Functor = ...)不正确?有没有不同的方法来制作这个别名?注意,在回答第二个问题时,如果解是 const 表达式就可以了,只是例子不是constexpr,因为使用了typeid

【问题讨论】:

  • @Jarod42 仍然失败了两个断言:/
  • 您要解决的实际问题是什么?为什么你认为你需要这个别名?
  • @Barry 我想消除在我需要的 3 个地方重复定义的需要。我宁愿定义一次并在其他任何地方使用别名
  • @Howard 的定义是什么?为了什么?为了做什么? 实际问题是什么?很容易回答为什么您的断言失败,但我什至不知道它们为什么在那里以及您要测试什么,所以我无法真正回答如何解决它。
  • 我不是要求另一个解决方案。我只是问它的写作方式有什么问题。为什么这不是我所期望的?令我感到惊讶的是,它并没有像写的那样工作,我想知道为什么。

标签: c++ templates c++17


【解决方案1】:

为什么第一个声明(使用typename Functor = ...)不正确?

您正在为模板参数Functor 提供默认类型。但是只有在没有另外指定或推导类型时才使用默认类型。在这种情况下,模板推导将在这两种情况下推导出 Functor 为调用它的 lambda 的唯一类型(而 Args... 推导为空包)。

这类似于在提供时不使用默认函数参数。

我不确定您的assert()s 应该完成什么,但如果您要检查类型,您应该使用static_assert

【讨论】:

  • 啊,现在说得通了。我不知道它会尝试推断默认模板参数。我的假设不正确,它只是在指定时不是默认值。断言仅在该代码中显示它没有按照我的意图执行,并阐明我的预期。上面的代码可以改写为std::function&lt;&gt;类型的别名吗?
  • @Howard 你的意思是像using T = int;
  • using 语句完全一样。我从文档中不完全了解我是否可以使用它,以便创建的别名仅作用于函数并且仍可用于命名参数类型
猜你喜欢
  • 2011-10-07
  • 1970-01-01
  • 2012-09-08
  • 2017-05-29
  • 2020-07-09
相关资源
最近更新 更多