在C ++ 11 / C ++ 14中,
template <
typename T ,
template <typename...> class Container_t
>
void MyFunc(Container_t<T> &data) { ... }
template <typename T>
void MyFunc2( T v ) { ... }
int main()
{
std::vector<char> v;
MyFunc<char, std::vector>(v); // OK
MyFunc(v); // error
int i;
MyFunc2<int>(i); // OK
MyFunc2(i); // OK
}
我在MyFunc(v)
时遇到错误。
是否有可能让编译器找出传递给可变参数模板函数的容器类型?我发现找出它没有任何问题,就像普通模板中的普通类型一样。
如果我需要更改v的类型,是否必须修复对MyFunc的所有调用?
编译器:Microsoft Visual C ++ 2015(v140)
答案 0 :(得分:8)
假设容器定义它存储的类型,而不是尝试推断容器类型。
template <typename Container>
void MyFunc(Container& data)
{
// all std containers defines value_type member (also reference etc.)
using std::begin;
using value_type = typename Container::value_type;
value_type value = *begin(data);
...
}
请注意,您可能根本不需要存储元素的类型:
template <typename Container>
void MyFunc(Container& data)
{
using std::begin;
auto value = *begin(data);
...
}
如果您只想处理std容器(或具有类似模板参数的容器) - 请参阅Richard Hodges answer。
答案 1 :(得分:4)
诀窍是命名模板的模板参数:
#include <vector>
#include <iostream>
#include <typeinfo>
template <
typename T ,
typename A,
template <typename = T, typename = A> class Container_t
>
void MyFunc(Container_t<T, A> &data) {
std::cout << "value type = " << typeid(T).name() << std::endl;
std::cout << "allocator type = " << typeid(A).name() << std::endl;
std::cout << "container type = " << typeid(Container_t<T,A>).name() << std::endl;
}
template <typename T>
void MyFunc2( T v ) { }
int main()
{
std::vector<char> v;
MyFunc<char, std::allocator<char>, std::vector>(v); // OK
MyFunc(v); // now ok
}
如果您不关心价值类型和容器之外的任何事情......
#include <vector>
#include <map>
#include <iostream>
#include <typeinfo>
template <
typename T ,
typename...Rest,
template <typename, typename...> class Container_t
>
void MyFunc(Container_t<T, Rest...> &data) {
std::cout << "value type = " << typeid(T).name() << std::endl;
std::cout << "container type = " << typeid(Container_t<T,Rest...>).name() << std::endl;
}
template <typename T>
void MyFunc2( T v ) { }
int main()
{
std::vector<char> v;
std::map<char, int> m;
// MyFunc<char, std::allocator<char>, std::vector>(v); // OK
MyFunc(v); // now ok
MyFunc(m); // now ok
}
答案 2 :(得分:1)
我的猜测是它是一个VC ++错误,因为GCC和CLANG可以推断出输入模板参数。正如KerrekSB在评论中提出的那样,一个不那么痛苦的解决办法如下:
writeErrorStream : True
PSMessageDetails :
Exception : System.Management.Automation.RuntimeException: A directory not found
error occurred while registering scheduled job definition testing.
Make sure you are running Windows PowerShell with elevated privileges.
---> Microsoft.PowerShell.ScheduledJob.ScheduledJobException: An error
occurred while registering scheduled job definition testing to the
Windows Task Scheduler. The Task Scheduler error is: The system cannot
find the path specified. (Exception from HRESULT: 0x80070003). --->
System.IO.DirectoryNotFoundException: The system cannot find the path
specified. (Exception from HRESULT: 0x80070003)
at TaskScheduler.ITaskService.GetFolder(String Path)
at Microsoft.PowerShell.ScheduledJob.ScheduledJobWTS.GetRootFolder()
at
Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition.AddToWTS()
at
Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition.Register()
--- End of inner exception stack trace ---
at
Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition.Register()
at Microsoft.PowerShell.ScheduledJob.RegisterScheduledJobCommand.Proc
essRecord()
--- End of inner exception stack trace ---
TargetObject : Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition
CategoryInfo : ObjectNotFound:
(Microsoft.Power...edJobDefinition:ScheduledJobDefinition)
[Register-ScheduledJob], RuntimeException
FullyQualifiedErrorId : DirectoryNotFoundWhenRegisteringScheduledJobDefinition,Microsoft.PowerSh
ell.ScheduledJob.RegisterScheduledJobCommand
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}