在下面的代码中,类模板使用一个参数,但如果模板参数是模板,则函数模板使用两个参数。这在使用类型推导时是可以的,但在使用显式模板实例化时很奇怪。
是否可以将模板模板参数写为一个单独的参数?
此问题与function overload matching template template
相关联#include <iostream>
template <typename T>
struct C
{
C (T i)
{
std::cout << "simple" << std::endl;
}
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> > // (1)
{
C (FF<TT> i)
{
std::cout << "template" << std::endl;
}
};
template <typename T>
void F (T i)
{
std::cout << "simple" << std::endl;
}
// two template arguments FF and TT.
// Anyway to write this so that the argument count is one?
template <template<typename TT> class FF, typename TT>
void F (FF<TT> i)
{
std::cout << "template" << std::endl;
}
template <typename T>
struct R
{
T x;
};
int main()
{
R<int> r;
C<R<int> >{r}; // prints 'template', as expected
F<R<int> >(r); // prints 'simple', probably not what you think
F<R,int >(r); // prints 'template' as expected but
}
编辑:
我得出的结论是问题不是很好,因为如果有一个参数语法,重载决议仍会选择错误的函数。这对我来说是一个惊喜,但这里是证明它的代码(除了一个模板函数重载改变之外,代码与之前相同):
EDIt2:在主要内容中添加了一个跳过显式模板规范的打印件。
EDIT3:以下代码是无意义的。我错了,因为@DyP指出正确。我在明确的情况下拨打void F(R<R<T>>)
而不是void F(R<T>)
。
#include <iostream>
template <typename T>
struct R
{
T x;
};
template <typename T>
struct C
{
C (T i)
{
std::cout << "simple" << std::endl;
}
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> > // (1)
{
C (FF<TT> i)
{
std::cout << "template" << std::endl;
}
};
template <typename T>
void F (R<T> i)
{
std::cout << "template" << i.x << std::endl;
}
template <typename T>
void F (T i)
{
std::cout << "simple" << std::endl;
}
int main()
{
R<int> r;
C<R<int> >{r}; // prints 'template', as expected
F<R<int> >(r); // prints 'simple', probably not the expected overload
F (r); // prints 'template', now overload resolution works. Strange.
}
答案 0 :(得分:1)
使用SFINAE:
#include <type_traits>
template<class T>
struct is_template_with_one_param
: std::false_type
{};
template<template<class> class TT, class T>
struct is_template_with_one_param< TT<T> >
: std::true_type
{};
#include <iostream>
template <typename T>
typename std::enable_if< not is_template_with_one_param<T>{}, void >::type
F (T i)
{
std::cout << "simple" << std::endl;
}
template <typename T>
typename std::enable_if< is_template_with_one_param<T>{}, void >::type
F (T i)
{
std::cout << "template" << std::endl;
}
用法示例:
template <typename T>
struct R
{
T x;
};
int main()
{
F(R<int>{});
F(42);
}
或者,请考虑Jarod42的suggestion。
答案 1 :(得分:0)
另一种可能的解决方案:
#include <iostream>
template <typename T>
struct C
{
C (T i)
{
std::cout << "simple" << std::endl;
}
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> > // (1)
{
C (FF<TT> i)
{
std::cout << "template" << std::endl;
}
};
template <typename T>
void F (T i)
{
C<T> x(i);
}
template <typename T>
struct R
{
T x;
};
int main()
{
R<int> r;
F(r);
F(4);
}