为什么模板参数推导/替换失败了std :: tuple和模板派生类?

时间:2017-09-13 04:04:11

标签: c++ c++11 templates

在下一个代码中,当我尝试将std::tuple引用派生类作为参数传递给接收std::tuple引用基类的函数时,模板参数推导失败。为什么编译器不能推导出模板参数T1T2?我该如何解决?

// Example program
#include <iostream>
#include <tuple>

template<typename T>
struct Base {};

template<typename T>
struct Derived1 : Base<T> {};

template<typename T>
struct Derived2 : Base<T> {};

template<typename T1, typename T2>
void function(std::tuple<Base<T1>&,Base<T2>&> arg)
{
    std::cout << "Hello\n";
}

int main()
{
    Derived1<int> d1;
    Derived2<double> d2;

    //function(std::tie(d1, d2));  /* In this case the template argument deduction/substitution failed */
    function<int,double>(std::tie(d1, d2)); /* here works */

    Base<int>& b1 = d1;
    Base<double>& b2 = d2;

    function(std::tie(b1, b2)); /* but, in this case also works */
}

这是行代码function(std::tie(d1, d2));的编译错误:

 In function 'int main()':
25:30: error: no matching function for call to 'function(std::tuple<Derived1<int>&, Derived2<double>&>)' 
25:30: note: candidate is: 
15:6: note: template<class T1, class T2> void function(std::tuple<Base<T>&, Base<T2>&>) 
15:6: note: template argument deduction/substitution failed: 
25:30: note: mismatched types 'Base<T>' and 'Derived1<int>' 
25:30: note: 'std::tuple<Derived1<int>&, Derived2<double>&>' is not derived from 'std::tuple<Base<T>&, Base<T2>&>' 

1 个答案:

答案 0 :(得分:1)

扣除不起作用。它在任何转换之前拉入或等等。在这里,编译器期望Base<T>从中推导T,并且您尝试传递DerivedN<T>。从类型系统的角度来看,它们是完全不同的野兽,当试图找到一个匹配良好的呼叫时,该功能被丢弃。
看看这个错误,很明显。

  

我该如何解决?

你可以使用这样的东西让它们被接受并仍然强迫它们来自Base

#include<type_traits>

// ...

template<template<typename> class C1, template<typename> class C2, typename T1, typename T2>
std::enable_if_t<(std::is_base_of<Base<T1>, C1<T1>>::value and std::is_base_of<Base<T2>, C2<T2>>::value)>
function(std::tuple<C1<T1>&, C2<T2>&> arg)
{
    std::cout << "Hello\n";
}

// ...

wandbox上查看并运行。