给出以下函数模板:
#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
我采取四种算法是完全不同的,因为他们使用什么数据结构相同-两个用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++ 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中实际执行此操作吗?我不能为我的生活思考如何.
以下代码在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) 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
在调试某人讨厌的宏生成的代码时,我看到仅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
当我使用参数包时,我注意到这样一种情况(如下所示)在 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
我有一个函数模板,该函数至少接受一个参数并对其余参数执行一些格式化:
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
在 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++ 代码示例,但我无法弄清楚为什么编译器以这种方式工作,尽管我花了很多时间研究 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