调用时模板参数推导/替换失败

问题描述 投票:0回答:1

要么是我对 C++ 的理解有问题,要么是某个地方存在隐藏的拼写错误...我在这几个 LOC 上浪费了几个小时。

首先,我定义了一个

start()
方法:

template <typename FunctionResult, typename ...FunctionArgs>
inline std::shared_ptr<StoppableThread> start(
        std::function<FunctionResult(const bool&, FunctionArgs...)> function, FunctionArgs... args)
{ ... }

还有一些

threadedSearch()
lambda 函数:

std::function<void(const bool&,
        const Source&, Population&,
        const std::vector<Parameter>&,
        const size_t&, const size_t&)> threadedSearch = ... ;

但是当我尝试执行此操作时:

Source source = { ... };
Population population = { ... };
const std::vector<Parameter> variationsParameters = { ... };
const size_t randomCandidatesCount = ..., lineageCount = ...;

auto searchThread = start(
    threadedSearch,
    source, population,
    variationsParameters,
    randomCandidatesCount, lineageCount);

编译器不同意后者对

starŧ()
的调用,并告诉我:

# with g++
error: no matching function for call to
‘start(std::function<void(const bool&, const Source&, Population&, const std::vector<Parameter>&, const long unsigned int&, const long unsigned int&)>&,
Source&, Population&, const std::vector<Parameter>&, const size_t&, const size_t&)’
[...]
note: candidate: ‘template<class FunctionResult, class ... FunctionArgs> std::shared_ptr<StoppableThread>
start(std::function<FunctionResult(const bool&, FunctionArgs ...)>, FunctionArgs ...)
note: template argument deduction/substitution failed:
note: inconsistent parameter pack deduction with ‘const Source&’ and ‘Source’

# with clang++
error: no matching member function for call to 'start'
note: candidate template ignored: deduced conflicting types for parameter 'FunctionArgs'
(<const Source&, Population&, const std::vector<Parameter>&, const unsigned long&, const unsigned long&>
vs.
<Source, Population, std::vector<Parameter>, size_t, size_t>)

我的问题是:WTF?

还有:我能做什么?在

start<...>()
调用中显式指定模板参数甚至不起作用...

我不知道如何让编译器理解它应该看到的“真实”参数类型......

可以在这里找到完全崩溃的最小示例:https://onlinegdb.com/FtBIGmkH-

编辑

好的,用它来编译:

auto searchThread = start<void, const Source&, Population&, const std::vector<Parameter>&, const size_t&, const size_t&>(
        threadedSearch,
        source, population,
        parameters,
        randomCandidatesCount, lineageCount);

谢谢你们,隔离一个最小的示例确实帮助我进行了调试!

c++ templates variadic-templates
1个回答
0
投票
whatever_t start(std::function<FunctionResult(const bool&, FunctionArgs...)> function, 
          FunctionArgs... args) 

这出现了两次

FunctionArgs...
。当属于
std::function
类型的一部分时,上下文是不可推导的,并且包将按原样从
std::function
中获取。在另一种情况下,上下文是可推导的,因此包将从实际的函数参数中推导出来。

在两种情况下,两个包都应该完全相同。然而

FunctionArgs... args
永远不会推导出引用类型,并且你的函数接受 const 引用。因此,一个包将充满 const 引用类型,而另一个包将充满非引用类型。这是替换失败。

解决该问题的一种方法是使其他事件也不可推论。

whatever_t start(std::function<FunctionResult(const bool&, FunctionArgs...)> function, 
      std::type_identity_t<FunctionArgs>... args)

将完成这项工作(需要 C++20,但可以在紧要关头实现相当于

std::type_identity_t
的功能)。

另一种方法是将函数类型与参数解耦。

template<typename Func, typename ... Args>
whatever_t start(Func&& func, Args&& ... args) 

(为了确保可以使用

func
调用
args
,您可以使用
requires
子句或老式的 SFINAE,或者直接调用它,并在无法调用时处理不太有用的错误消息),

© www.soinside.com 2019 - 2024. All rights reserved.