C ++模板参数推导失败

时间:2016-09-20 17:57:51

标签: c++ templates sfinae typetraits

为什么编译器可以使用以下代码推导出T:

#include <vector>

template<typename T>
void foo(T& t) {}

int main(void) {
    std::vector<uint8_t> vec = { 1,2,3 };
    foo(vec);
    return 0;
}

但是这段代码失败了:

#include <vector>
#include <type_traits>

template<typename T>
void foo(typename std::enable_if<true, T>::type& t) {}

int main(void) {
    std::vector<uint8_t> vec = { 1,2,3 };
    foo(vec);
    return 0;
}

我想使用第二个构造,在两个模板函数之间进行选择,基于传递的类方法存在。

3 个答案:

答案 0 :(得分:6)

在第二种情况下,您有non-deduced context,换句话说,编译器无法推断出类型。

非推断上下文的最简单示例是

template<typename T>
struct Id
{
    using type = T;
};

template<typename T>
void foo(typename Id<T>::type arg); // T cannot be deduced

答案 1 :(得分:4)

正如vsoftco所解释的那样,你有一个非推断的背景。

对于SFINAE,您可以使用以下其中一项:

template<typename T>
std::enable_if_t<condition_dependent_of_T, ReturnType>
foo(T& t) {}

template<typename T, std::enable_if_t<condition_dependent_of_T>* = nullptr>
ReturnType foo(T& t) {}

答案 2 :(得分:2)

为了使问题可视化,让我们分析一个例子:

template <class>
struct foo { 
    using type = float;
};

template <>
struct foo<bool> {
    using type = int;
};

template <>
struct foo<int> {
    using type = int;
};

template <class T>
void bar(foo<T>::type t) { }

int main() {
   bar(int{}); 
}

现在在bar(int{});行中,boolint两种类型都与模板参数T匹配。那么应该推导出哪一个值?这只是为什么非推断上下文是绝对必要的一个例子!