我采取四种算法是完全不同的,因为他们使用什么数据结构相同-两个用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中实际执行此操作吗?我不能为我的生活思考如何.
我想通过其他模板参数指定模板化函数的返回类型。所有这些都在一个班级中。
在头文件中:
class MyClass {
template<int type, typename RT>
RT myfunc();
};
Run Code Online (Sandbox Code Playgroud)
在 .cpp 中是这样的:
template<>
int MyClass::myfunc<1, int>() { return 2; }
template<>
double MyClass::myfunc<2, double>() { return 3.14; }
template<>
const char* MyClass::myfunc<3, const char*>() { return "some string"; }
Run Code Online (Sandbox Code Playgroud)
我希望能够像这样使用我的功能:
MyClass m;
int i = m.myfunc<1>(); // i will be 2
double pi = m.myfunc<2>(); // pi will be 3.14
const char* str = m.myfunc<3>(); // str == "some string"
Run Code Online (Sandbox Code Playgroud)
所以我希望我的函数能够通过一个模板整数(或任何枚举)进行参数化,并且基于这个整数,返回类型会有所不同。我不希望该函数使用指定参数以外的任何其他整数参数,例如这里m.myfunc<4>()会产生编译错误。
我只想通过一个模板参数来参数化我的函数,因为它m.myfunc<1, int>()可以工作,但我不想一直写类型名。 …
以下代码在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) 在调试某人讨厌的宏生成的代码时,我看到仅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
以下代码无法编译;g++ 7.3.0 with--std=c++17给出了错误信息
constexpr 函数 'constexpr const C operator+(const C&, int)' 的无效返回类型 'const C'
注意:'C' 不是文字,因为 'C' 有一个非平凡的析构函数
#include <string>
using namespace std ;
struct C
{
C (std::string s) : s (s) { }
std::string s ;
} ;
constexpr const C operator+ (const C& x, int y) // <-- Error here
{
return C ("C int") ;
}
int main()
{
C c ("abc") ;
printf ("%s\n", (c + 99).s.c_str()) ;
}
Run Code Online (Sandbox Code Playgroud)
好吧,好吧。但是如果我添加一个看似无关的模板规范到operator+:
template<typename …Run Code Online (Sandbox Code Playgroud) 我想编写一个M接受不完整类型C作为模板参数的类模板。但我也希望C在最终定义时具有一些特征。
此代码是否有保证
template <auto> struct Dummy {};
template <typename C>
void check()
{
static_assert(std::is_trivial_v<C>);
}
template <typename C>
struct M : Dummy<&check<C>>
{
//static_assert(std::is_trivial_v<C>);//error: incomplete type
C * p;
};
struct Test;
M<Test> m;
int main()
{
return 0;
}
#if defined(FLAG)
struct Test {};
#else
struct Test { std::string non_trivial_member; };
#endif
Run Code Online (Sandbox Code Playgroud) c++ language-lawyer function-templates implicit-instantiation non-type-template-parameter
我有这样的代码:
template<class Command>
void registerCmd() {
Command x{};
// do something with x...
}
namespace Cmd
{
struct GET { /* some methods */ };
struct GETSET { /* some methods */ };
struct DEL { /* some methods */ };
void registerCommands() {
registerCmd<GET>();
registerCmd<GETSET>();
registerCmd<DEL>();
}
}
Run Code Online (Sandbox Code Playgroud)
我喜欢代码的结果。我想知道是否有办法将此代码更改为如下所示:
namespace Cmd
{
void register() {
// this does not compile
for (TYPE in{ GET, GETSET, DEL })
registerCmd<TYPE>();
}
}
Run Code Online (Sandbox Code Playgroud)
可以使用可变参数模板吗?
当我使用参数包时,我注意到这样一种情况(如下所示)在 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++ ×10
templates ×5
c++11 ×2
c++17 ×2
clang ×1
gcc ×1
non-type-template-parameter ×1
return-type ×1
stl ×1