【问题标题】:Declaring function templates before defining when overloading在重载定义之前声明函数模板
【发布时间】:2015-11-20 23:10:20
【问题描述】:

C++ Primer 5th Edition 在第 16.3 章(讨论函数模板重载的一章)末尾有一个 sn-p 建议:

在定义任何重载集之前声明重载集中的每个函数 职能。这样你就不必担心编译器是否会 在它看到你要调用的函数之前实例化一个调用。

这是否告诉我,在重载决议期间选择候选函数和可行函数时,编译器可能会实例化最终没有选择的函数模板?我试图看看这是否真的会发生:

template<class> struct always_false : std::false_type {};

template <typename T> void test(T const &){
    static_assert(always_false<T>::value, "If this fires, it is instantiated");
}

template <typename T> void test(T*) {   }

int main(){
    int *q = nullptr; 
    test(q); //test(T*) should be the best match
}

如果test(T const &amp;) 以任何形式实例化,该程序将引发编译器错误,除非程序按预期编译正常。那么这个提示试图保护我免受什么样的编译事故呢?它什么时候会在看到我试图调用的函数之前实例化一个函数?

【问题讨论】:

标签: c++ templates c++11 overloading


【解决方案1】:

作者警告你:

template<class> struct always_false : std::false_type {};

template <typename T> void test(T const &){
   static_assert(always_false<T>::value, "If this fires, it is instantiated");
}

int main(){
    int *q = nullptr; 
    test(q); //test(T*) will not be matched.
}

template <typename T> void test(T*)
{ 
}

还有这些:

template<class> struct always_false : std::false_type {};

template <typename T> void test(T const &){
   static_assert(always_false<T>::value, "If this fires, it is instantiated");
}

template <> void test<int>(int const &);

void test(int *);

int main(){
   int *q = nullptr; 
   test(q); //test(int*) should be the best match
   int a;
   test(a); // test<int>(int const&) should be the best match
}

template <> void test<int>(int const &)
{
}

void test(int *)
{ 
}

如果你不提供声明

template <> void test<int>(int const &);

void test(int *);

main 之前,它们不会在main 中匹配。

【讨论】:

  • 在它看到您打算调用的函数之前。“之前”让我感到困惑,在您提供的示例中 test(T*) 永远不会看到 @987654327 @ 有没有。如果这真的是这本书所暗示的足够公平的话,但它似乎更像是关于保持范围内的事情而不是与模板有关的任何事情。
  • @AntiElephant,既然你已经接受了我的回答,我会假设你已经回答了你的问题。
【解决方案2】:

我见过很多这样的问题是一些变化

template<class T, class... Ts>
T sum(T t, Ts... ts) { return t + sum(ts...); }
// ^                               |
// |--------------------------------
//    only one visible in 
//     definition context

template<class T>
T sum(T t) { return t; }

int main() {
    sum(1, 2); // doesn't compile
}

(返回类型并不完美,但你明白了。)

然后当它不编译时人们会感到惊讶。

或者,更有趣的是,

template<class T> void f(T t) { f((int)t); }
void f(int) { /*...*/ }

int main() { 
    f(1L); // infinite recursion
}

【讨论】:

  • 除非 T sum(T t) 在实例化点被 ADL 发现(这里不是这种情况),这使它更加有趣。例如,在全局范围内拥有 struct Foo{ Foo operator+(const Foo&amp;){return *this;}}; 并在 main() 内调用 sum(Foo{}, Foo{}); 将编译。
猜你喜欢
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多