标签: function-templates

为什么编译器在以下示例中没有选择我的函数模板重载?

给出以下函数模板:

#include <vector>
#include <utility>

struct Base { };
struct Derived : Base { };

// #1
template <typename T1, typename T2>
void f(const T1& a, const T2& b)
{
};

// #2
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};
Run Code Online (Sandbox Code Playgroud)

为什么以下代码总是调用#1而不是#2重载?

int main()
{
    std::vector<std::pair<int, int> > v;
    Derived derived;

    f(100, 200);  // clearly calls overload #1
    f(v, &derived);         // always calls overload #1

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

鉴于第二个参数f是派生类型Base,我希望编译器选择重载#2,因为它比重载#1中的泛型类型更好. …

c++ templates overloading function-templates overload-resolution

5
推荐指数
2
解决办法
329
查看次数

如何编写可以接受堆栈或队列的函数模板?

我采取四种算法是完全不同的,因为他们使用什么数据结构相同-两个用priority_queue,一个用途stack,最后的用途queue.它们相对较长,所以我想只有一个函数模板接受容器类型作为模板参数,然后让每个算法用适当的参数调用该模板,如下所示:

template <class Container>
void foo(/* args */)
{
    Container dataStructure;
    // Algorithm goes here
}

void queueBased(/* args */)
{
    foo<queue<Item> >(/* args */);
}

void stackBased(/* args */)
{
    foo<stack<Item> >(/* args */);
}
Run Code Online (Sandbox Code Playgroud)

我已经成功地使用priority_queue- 和 - stack基础实现,但我不能对queue基于算法的算法做同样的事情,因为它使用不同的名称来访问最重要的元素(front( )而不是top( )).我知道我可以专门针对这种情况使用模板,但后来我会有大量的重复代码(这是我要避免的).

实现这一目标的最佳方法是什么?我的第一个本能是为队列创建一个包装类,它添加了一个top( )等同于stack's 的操作,但我一直在读这个子类化STL类是一个禁忌.那我该怎么办呢?

c++ templates stl function-templates

5
推荐指数
1
解决办法
1335
查看次数

在C++ 11中,如何根据返回类型对一个函数对象进行专门化?

我在C++ 11中有一个包装函数,设计用于lambdas,如下所示:

template<typename Func>
int WrapExceptions(Func&& f)
{
  try
  {
    return f();
  }
  catch(std::exception)
  {
    return -1;
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以这样称呼它:

int rc = WrapExceptions([&]{
  DoSomething();
  return 0;
});
assert(rc == 0);
Run Code Online (Sandbox Code Playgroud)

生活还可以.但是,我想要做的是重载或专门化包装函数,这样当内部函数返回void时,外部函数返回默认值0,例如:

int rc = WrapExceptions([&]{
  DoSomething();
});
assert(rc == 0);
Run Code Online (Sandbox Code Playgroud)

我可以在C++ 11中实际执行此操作吗?我不能为我的生活思考如何.

c++ templates function-templates c++11

5
推荐指数
1
解决办法
380
查看次数

基于嵌套类型的模板函数选择

以下代码在VS2015上正常工作:

struct Foo
{
   using Bar = int;
   auto operator()() { return "Foo!";  }
};

template <typename Callable, typename CodeType> // <<< CodeType is a template param
void funky(CodeType code, Callable func)
{
   cout << "Generic: " << code << ", " << func() << endl;
}

template <typename HasBar>
void funky(typename HasBar::Bar code, HasBar func) // <<< The code type is a nested type
{
   cout << "Has Bar: " << code << ", " << func() << endl; …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang function-templates visual-studio-2015

5
推荐指数
1
解决办法
159
查看次数

重载可变长度模板函数的递归结束

FrançoisAndrieux为我解决了Visual Studio 2017问题提供了一个很好的解决方法。我试图像这样回答他:

template<class T, size_t N>
ostream& vector_insert_impl(ostream& lhs, const char*, const T& rhs)
{
    return lhs << at(rhs, N);
}

template<class T, size_t N, size_t... I>
ostream& vector_insert_impl(ostream& lhs, const char* delim, const T& rhs)
{
    return vector_insert_impl<T, I...>(lhs << at(rhs, N) << delim, delim, rhs);
}

template <typename T, size_t... I>
ostream& vector_insert(ostream& lhs, const char* delim, const T& rhs, index_sequence<I...>) 
{
    return vector_insert_impl<T, I...>(it, delim, rhs);
}
Run Code Online (Sandbox Code Playgroud)

关键区别在于,“递归结束”模板函数实际上将最后一个值插入ostream而不是分隔符,而不是无操作。但是当我尝试编译它时,我得到了错误:

错误C2668 …

c++ recursion variadic-functions function-templates variadic-templates

5
推荐指数
1
解决办法
74
查看次数

合法使用非跟踪功能模板参数包?

在调试某人讨厌的宏生成的代码时,我看到仅MSVC ++对类似于以下函数模板声明的内容不满意:

template <typename ...Vs, typename>
void foo();
Run Code Online (Sandbox Code Playgroud)

很公平。我对为什么GCC和Clang会编译它感到困惑。我foo在上面的声明中添加了的定义,现在GCC也产生了编译错误(Clang仍然存在)。此代码如下:

template <typename ...Vs, typename>
void foo();

template <typename ...Vs, typename = int>
void foo() {  }

int main(int argc, char *argv[])
{
  foo<char,float>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Clang是对还是错?我注意到,如果删除了声明,则GCC和MSVC ++可以编译。

c++ function-templates default-parameters variadic-templates c++11

5
推荐指数
1
解决办法
84
查看次数

函数模板重载解析期间的 MSVC 与 Clang/GCC 错误,其中一个函数模板包含参数包

当我使用参数包时,我注意到这样一种情况(如下所示)在 gcc 和 clang 中编译得很好,但在 msvc 中却不行:

template<class T> void func(T a, T b= T{})
{
    
}
template<class T, class... S> void func(T a, S... b)
{

}
 
int main()
{
    func(1); // Should this call succeed? 
}
Run Code Online (Sandbox Code Playgroud)

这是验证相同内容的链接:https://godbolt.org/z/8KsrcnMez

可以看到,上面的程序在 msvc 中失败,并显示错误消息:

<source>(13): error C2668: 'func': ambiguous call to overloaded function
<source>(6): note: could be 'void func<int,>(T)'
        with
        [
            T=int
        ]
<source>(2): note: or       'void func<int>(T,T)'
        with
        [
            T=int
        ]
<source>(13): note: while trying to match the argument list …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer function-templates pack-expansion parameter-pack

5
推荐指数
1
解决办法
226
查看次数

可变参数模板函数对非可变参数的特殊化

我有一个函数模板,该函数至少接受一个参数并对其余参数执行一些格式化:

template <typename T, typename... ARGS>
void foo(T first, ARGS&&... args)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

当第一个参数是特定类型时,我希望它做不同的事情。我喜欢编译器选择这个特定的版本,其中其余的可变参数被忽略。所以我尝试了模板专业化:

template <>
void foo(const ICON* p)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或者:

template <typename T, typename... ARGS>
void foo(const ICON* p, ARGS&&... args)
{
   // ...
}
Run Code Online (Sandbox Code Playgroud)

我还尝试了非模板化重载,但它总是选择第一个版本。

调用者代码应该根本不知道模板(遗留代码、向后兼容性废话等),因此它依赖于类型推导和如下调用:

MyClass fooMaker;
fooMaker.set("A", "B", 3.14, 42); // v1
fooMaker.set(pIcon);              // v2 (special)
Run Code Online (Sandbox Code Playgroud)

c++ templates function-templates overload-resolution variadic-templates

5
推荐指数
1
解决办法
230
查看次数

C++ 11 条件模板函数的别名

在 C++ 11 中,我想创建一个具有两个专业化的模板别名,每个专业化解析为不同的函数。

void functionA();
void functionB();

template<typename T = char>
using Loc_snprintf = functionA;

template<>
using Loc_snprintf<wchar_t> = functionB;
Run Code Online (Sandbox Code Playgroud)

所以我可以打电话给eg Loc_snprintf<>(),它决定了functionA()

显然似乎不可能(编译)。是否有一些最终简单的东西可以模仿它(也许使用类模板)?

c++ function-templates c++11 template-aliases

5
推荐指数
1
解决办法
124
查看次数

C++ 重载函数的地址

我有以下小的 C++ 代码示例,但我无法弄清楚为什么编译器以这种方式工作,尽管我花了很多时间研究 cppreference。我将不胜感激任何解释!神箭

#include <type_traits>

template<typename Tp>
struct depend_type
{
  constexpr static bool false_ = false;
};

template<typename Tp>
struct cont
{
  using x = void;

  static_assert(std::is_same_v<Tp, int>);
  // if uncomment, will be complie error -> 'cont<Tp>::x' instantiated with 'void (*p)(int) = func;'
//   static_assert(depend_type<Tp>::false_); 
};

template<typename Tp>
void func(Tp)
{
}

template<typename Tp>
typename cont<Tp>::x func(Tp);

int main(int /* argc */, char * /*argv*/[])
{
//  func(1); is ambiguous call
  void (*p)(int) = func; // why is …
Run Code Online (Sandbox Code Playgroud)

c++ function-templates overload-resolution template-meta-programming

5
推荐指数
1
解决办法
186
查看次数