2017-08-11 46 views
3

我正在学习一些关于C++的新概念,我正在玩他们。 我写了一段代码,它真的让我对它的工作方式感到困惑。类与类参数化和与帮助函数混淆

#include <iostream> 

class aid { 
public: 
    using aid_t = std::string; 
    void setaid(const std::string& s) { 
     aid_ = s; 
    } 
    const aid_t& getaid() const { 
     return aid_; 
    } 
private: 
    aid_t aid_; 
}; 

class c { 
public: 
    using c_t = std::string; 
    void setc(const aid::aid_t& aid_val) { 
     if (aid_val.size() < 4) 
      c_ = "yeah"; 
     else 
      c_ = aid_val + aid_val; 
    } 
    const c_t& getc() { 
     return c_; 
    } 
private: 
    c_t c_; 
}; 

template<typename ...Columns> 
class table : public Columns... { 
}; 

template <typename... Columns> 
void f(table<Columns...>& t) { 
    t.setaid("second"); 
    std::cout << t.getaid() << "\n"; 
} 

void f2(table<aid>& t) { 
    t.setaid("third"); 
    std::cout << t.getaid() << "\n"; 
} 

int main() { 
    table<aid, c> tb; 
    tb.setaid("first"); 
    std::cout << tb.getaid() << " " << "\n"; 
    // f<c>(tb); // (1) doesnt compile, that seem obvious 
    f<aid>(tb); // (2) works? 
    f(tb); // (3) works too -- template parameter deduction 
    // f2(tb); // (4) doesnt work? worked with (2)... 
} 

这里的想法很简单,我有一些列的表。然后,我想创建一些函数,只需要一些列的集合,并不在乎如果传递的参数有一些额外的列。 (2)和(4)在代码中...我的直觉认为它应该是相同的,为什么不是这样,(2)编译和(4)不是这样?是否有任何重要的主题我错过了,应该阅读? 有没有办法实现这个特定的功能?干杯

回答

3

在第二种情况下,编译器仍然会推导出模板参数包的其余部分,以便您获取table<aid, c> &作为函数参数。这与(4)(table<aid> &)不同。

[temp.arg.explicit]/3:从默认模板参数获得 可以推断

尾随模板参数(14.8.2),或者可以从 明确的模板的参数列表被省略。未另外推导出的尾随模板参数包 (14.5.3)将被推导为模板参数的空序列 。如果可以推导出所有模板参数,则可以全部省略它们;在这种情况下,空模板参数<>本身也可以被省略。在扣除是 完成和失败的上下文中,或者在未完成扣除的上下文中,如果指定了 模板参数列表,并且它与任何默认的 模板参数一起标识了单个函数模板 专用化, id是功能 模板专用化的左值。