c++ - 为什么只有一个参数的可变参数模板与非可变参数模板不同?

标签 c++ c++11 templates variadic-templates type-deduction

这段代码编译得很好:

template <typename T1>
struct Struct {
};

struct ConvertsToStruct {
    operator Struct<int>() const;
};

template <typename T>
void NonVariadicFunc(Struct<T>);

int main() {
      NonVariadicFunc<int>(ConvertsToStruct{});
      return 0;
}

但试图通过使用可变参数模板使其更通用一些,但编译失败:

template <typename T1>
struct Struct {
};

struct ConvertsToStruct {
    operator Struct<int>() const;
};

template <typename... T>
void VariadicFunc(Struct<T...>);

int main() {
      VariadicFunc<int>(ConvertsToStruct{});
      return 0;
}

怎么了?为什么我尝试显式指定 VariadicFunc 的模板类型没有成功?

Godbolt 链接 => https://godbolt.org/g/kq9d7L

最佳答案

有两个原因可以解释为什么这段代码无法编译。

首先,模板函数的模板参数可以部分指定:

template<class U, class V> void foo(V v) {}

int main() {
      foo<double>(12);
}

此代码有效,因为您指定了第一个模板参数 U并让编译器确定第二个参数。出于同样的原因,你的 VariadicFunc<int>(ConvertsToStruct{});还需要模板参数推导。这是一个类似的例子,它编译:

template<class... U> void bar(U... u) {}

int main() {
      bar<int>(12.0, 13.4f);
}

现在我们知道编译器需要对你的代码进行推导,接下来是第二部分:编译器按照固定的顺序处理不同的阶段:

cppreference

Template argument deduction takes place after the function template name lookup (which may involve argument-dependent lookup) and before template argument substitution (which may involve SFINAE) and overload resolution.

隐式转换发生在重载解析时, 模板参数推导之后。因此,在您的情况下,当编译器进行模板参数推导时,用户定义的转换运算符的存在无效。显然ConvertsToStruct本身无法匹配任何东西,因此推导失败,代码无法编译。

关于c++ - 为什么只有一个参数的可变参数模板与非可变参数模板不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48630866/

相关文章:

c++ - 紧凑、可读、高效的 C++ 算法,用于反转字符串中的单词 IN-PLACE

c++ - 根据某个功能是否存在启用模板

c++ - 多种类型的模板特化

c# - Windows 的声音管理器类

c++ - 如何在函数指针中模板化参数?

c++ - 复制和粘贴 .so 文件不适用于链接器

c++ - 双向链表节点插入位置

c++ - g++ : Compilation failed to deduce reference array in case of temporary object

c++ - 访问静态和非静态的模板构造函数和函数

C++:如何获得解耦的多态行为