当前位置: 首页 > 知识库问答 >
问题:

C模板特化的类型推导在ulus参数上失败

殷承恩
2023-03-14

我创建了一个模板类,其中构造函数采用std::function对象。第一个模板参数指示该函数的返回值。第二个参数定义该函数的参数类型。

#include <functional>

//Base
template<class R, class Arg>
class Executor {
    public:      
        Executor(std::function<R(Arg)> function) 
            : mFunction(function)  
        {}

    private:
        std::function<R(Arg)> mFunction;
};

//Specialization1
template<class Arg>
class Executor<void, Arg> {
    public:      
        Executor(std::function<void(Arg)> function) 
            : mFunction(function)  
        {}

    private:
        std::function<void(Arg)> mFunction;
};

//Specialization2
template<class R>
class Executor<R, void> {
    public:      
        Executor(std::function<R()> function) 
            : mFunction(function)  
        {}

    private:
        std::function<R()> mFunction;
};

int testBase(float value) {
    return 5;
}

void testSpecialization1(float value) {}

int testSpecialization2() {
    return 22;
}

int main() {
    Executor executorBase{std::function(testBase)};
    
    Executor executorSpecialization1{std::function(testSpecialization1)};
    
    //Executor<int, void> executorSpecialization2{std::function(testSpecialization2)}; // Compiles
    Executor executorSpecialization2{std::function(testSpecialization2)}; // Doesn't compile. Uses Base. template<class R, class Arg>
}

关于使用函数std::function

main.cpp: In function 'int main()':
main.cpp:55:72: error: class template argument deduction failed:
   55 |     Executor executorSpecialization2{std::function(testSpecialization2)}; // Doesn't compile. Uses Base. template<class R, class Arg>
      |                                                                        ^
main.cpp:55:72: error: no matching function for call to 'Executor(std::function<int()>)'
main.cpp:7:9: note: candidate: 'template<class R, class Arg> Executor(std::function<R(Arg)>)-> Executor<R, Arg>'
    7 |         Executor(std::function<R(Arg)> function)
      |         ^~~~~~~~
main.cpp:7:9: note:   template argument deduction/substitution failed:
main.cpp:55:72: note:   candidate expects 1 argument, 0 provided
   55 |     Executor executorSpecialization2{std::function(testSpecialization2)}; // Doesn't compile. Uses Base. template<class R, class Arg>
      |                                                                        ^
main.cpp:5:7: note: candidate: 'template<class R, class Arg> Executor(Executor<R, Arg>)-> Executor<R, Arg>'
    5 | class Executor {
      |       ^~~~~~~~
main.cpp:5:7: note:   template argument deduction/substitution failed:
main.cpp:55:72: note:   'std::function<int()>' is not derived from 'Executor<R, Arg>'
   55 |     Executor executorSpecialization2{std::function(testSpecialization2)}; // Doesn't compile. Uses Base. template<class R, class Arg>
      |

它尝试使用基本版本。但第二个参数当然丢失了。如果我指定它编译的模板参数。

那么,为什么选择基本模板作为executorSpecialization2呢?甚至可以在这里对void使用类型推断,而不需要传递模板参数吗?

谢啦

共有2个答案

吴康平
2023-03-14

int(val)仅在狭窄的情况下可用作int()

像这样改变它:

template<class R, class... Args>
class Executor

并将参数替换为参数

NixR, val专业化。

如果需要类执行

您的代码现在将编译一个作品。

(产生错误的原因:隐式生成的扣除指南仅基于主要专门化。std::function(testSpecialization2)std::function

劳高爽
2023-03-14

当您使用名称Executor时,没有像Executor中那样的显式模板参数

主模板具有构造函数Execitor(std::function

但是看到std::f

但您可以通过编写“扣除指南”来协助CTAD:

template <class R>
Executor(std::function<R()>) -> Executor<R, void>;

除主模板的构造函数外,还使用扣除指南。现在是一个类型为std::function的参数

看看它对coliru的作用。

 类似资料:
  • 我已经编写了一个具有递归评估的可变参数模板函数。对于最后一个参数,我在没有可变参数包的情况下实现了专业化,并且一切正常。 现在我想把可变函数参数转换成模板参数。 这是我的尝试: gcc和clang报告了一个模糊的过载,并且无法使用空参数包在“专业化”和“可变参数”之间做出决定。 我尝试删除特化并检查可变参数模板中的包大小,但是如果没有特化,编译器就无法推断出参数“p”。

  • 使用以下代码生成时 生成以下诊断(代码后): 诊断: 有趣的部分不是关于歧义错误本身(这不是这里主要关注的问题)。有趣的是,当仅使用函数名调用fun时,第一个fun的模板参数F被解析为纯函数类型double(double),而第二个fun的模板参数F被解析为更期望的函数指针类型。 然而,当我们将调用<代码>乐趣(测试) 更改为<代码>乐趣( 这种行为似乎是所有Clang和GCC(以及Visual

  • 考虑以下示例: 而且,如果我们将非类型模板参数的类型改为占位符类型,如下所示: 然后,GCC接受,而Clang拒绝它(两者都拒绝,如上)。 海合会演示,铿锵演示。 (1)GCC HEAD 11.0.0 202 10117和Clang HEAD 12.0.0(20210118),。

  • 另一个有用的可能示例:(伪代码)

  • 我试图在类型s. t上专门化一个类。它忽略了给定类型的恒定性。在这种情况下,该类型是一个模板模板参数: 上面的代码在GCC 4.8.4和clang 5.0(with-std=c 11)中都抱怨bar在与匹配FOFType模板参数化的类一起使用时未定义。即使我删除了sfinae参数,仍然无法找到特化。 这个问题的一个例子可以在这里找到:https://godbolt.org/g/Cjci9C.在上面

  • 我正在尝试编写一个简单的模板,我可以使用该模板对带有单个参数的函数进行记忆: 但我得到了一个错误: 错误:没有匹配函数来调用“备忘录(双精度)” 注:候选人是: 注意:模板OUT记忆(IN) 注意:模板参数扣除/替换失败: 为什么编译失败? 实际上,当我指定所有模板参数时,我不明白为什么模板参数推导/替换会发生。 我使用的是gcc版本4.7.2(未启用C 11) PS:模板的错误比我最初意识到的要