为什么我不能推导出类模板参数之一?

时间:2021-01-22 08:07:02

标签: c++ templates c++17 template-argument-deduction

我这里有一些代码

template<typename T, std::size_t size, typename funcType>
struct foo
{
public:

    foo(const funcType& func) : m_func(func) {}
    ~foo() {}
    
    void m_call() { m_func(); }

private:
    const funcType& m_func;

    T x[size];
};

void printString() { std::cout << "some string\n"; }

我可以创建一个对象

foo<int, 3, void(*)()> someObject(printString);

foo<int, 3, decltype(printString)> someObject(printString);

但是当我尝试这样做时:

foo<int, 3> someObject(printString);

我在 g++ 10.2 上遇到这个错误

error: wrong number of template arguments (2, should be 3)
 foo<int, 3> someObject(printString);
           ^
note: provided for 'template<class T, long unsigned int size, class funcType> struct foo'
 struct foo
       

为什么我不能这样做?编译器不知道 printString 是什么类型吗?

如果我将 foo 更改为

template<typename funcType>
struct foo
{
public:

    foo(const funcType& func) : m_func(func) {}
    ~foo() {}
    
    void m_call() { m_func(); }

private:
    const funcType& m_func;
};

我可以正常创建

foo someObject(printString);

我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

根据cppreference

<块引用>

类模板参数推导仅在没有模板的情况下进行 存在参数列表。如果指定了模板参数列表, 不发生扣减。

您的上次实验证实了这一点。要推断 funcType,您还需要在构造函数中提供其他模板化类型,以不提供任何模板参数列表。

您可以使用构造函数绑定其他模板,例如使用此构造:

#include <iostream>

template<typename T, std::size_t size, typename funcType>
struct foo
{
public:
    foo(T (&arr)[size], const funcType& func) : m_func(func) {}
    ~foo() {}

    void m_call() { m_func(); }

private:
    const funcType& m_func;
    T x[size]{};
};

void printString() { std::cout << "some string\n"; }


void test() {
    foo someObject("test", printString);

}

godbolt

答案 1 :(得分:1)

使用模板函数创建对象并从函数调用中扣除缺失的模板参数。像这样的东西。

template<typename T, std::size_t Size, typename FunctionT>
foo<T, Size, FunctionT> create_foo(const FunctionT &func) {
    return foo<T, Size, FunctionT>(func);
} 

auto foo_obj = create_foo<int, 3>(printString);