我正在尝试将函数模板的详细信息提取为模板参数。
#include <tuple>
template <typename T>
struct Generator
{
typedef int type;
int operator()(int i) const { return i; }
};
// old functions
template <
typename... Args,
typename... FArgs>
std::tuple<Args...> g(
std::tuple<Args...> & a,
FArgs&&... fargs)
{
return std::make_tuple( (Generator<Args>()(fargs...))... );
}
template <
typename Arg,
typename... FArgs>
std::tuple<Arg> g(
std::tuple<Arg> & a,
FArgs&&... fargs)
{
return std::make_tuple( (Generator<Arg>()(std::forward<FArgs>(fargs)...)) );
}
// new functions
template <
template <typename T> class F,
typename... Args,
typename... FArgs>
std::tuple<Args...> h(
std::tuple<Args...> & a,
FArgs&&... fargs)
{
return std::make_tuple( (F<Args>()(fargs...))... );
}
template <
template <typename> class F,
typename Arg,
typename... FArgs>
std::tuple<Arg> h(
std::tuple<Arg> & a,
FArgs&&... fargs)
{
return std::make_tuple( (F<Arg>()(std::forward<FArgs>(fargs)...)) );
}
int main()
{
auto t = std::make_tuple( 1 );
auto y = g(t, 2);
auto z = h<Generator>(t, 2); // ERROR
}
用clang编译好,但是使用gcc(4.9,5.3和6.2)我得到以下错误:
% g++ --std=c++11 test.cc
test.cc: In function ‘int main()’:
test.cc:56:28: error: call of overloaded ‘h(std::tuple<int>&, int)’ is ambiguous
auto z = h<Generator>(t, 2);
^
test.cc:34:21: note: candidate: std::tuple<_Elements ...> h(std::tuple<_Elements ...>&, FArgs&& ...) [with F = Generator; Args = {int}; FArgs = {int}]
std::tuple<Args...> h(
^
test.cc:45:17: note: candidate: std::tuple<Arg> h(std::tuple<Arg>&, FArgs&& ...) [with F = Generator; Arg = int; FArgs = {int}]
std::tuple<Arg> h(
这应该是不明确的吗?如果是这样,为什么对g
的调用也不明确?
答案 0 :(得分:0)
只需将您的新功能定义为:
template <
template <typename T> class F,
typename... Args,
typename... FArgs>
std::enable_if_t<(sizeof...(Args)>1), std::tuple<Args...>> h(
std::tuple<Args...> & a,
FArgs&&... fargs)
{
return std::make_tuple( (F<Args>()(fargs...))... );
}
template <
template <typename> class F,
typename Arg,
typename... FArgs>
std::tuple<Arg> h(
std::tuple<Arg> & a,
FArgs&&... fargs)
{
return std::make_tuple( (F<Arg>()(std::forward<FArgs>(fargs)...)) );
}
这将允许消除歧义并实际编译代码。
事实上,h
的两个实现都将tuple
和int
作为参数,只有一种类型的tuple
对它们都有效。
在这种情况下,sfinae表达式(参见enable_if_t
)强制选择h
的第二个实现,第一个实现所有其他实现。