C++ 计算为单个参数的模板模板参数
在下面的代码中,类模板使用一个参数,但如果模板参数是模板,则函数模板使用两个参数。这在使用类型推断时是正常的,但在使用显式模板实例化时是不正常的 是否可以将模板参数作为单个参数写入 这个问题与C++ 计算为单个参数的模板模板参数,c++,templates,function-templates,template-templates,C++,Templates,Function Templates,Template Templates,在下面的代码中,类模板使用一个参数,但如果模板参数是模板,则函数模板使用两个参数。这在使用类型推断时是正常的,但在使用显式模板实例化时是不正常的 是否可以将模板参数作为单个参数写入 这个问题与 #包括 模板 结构C { C(T i) { 标准::可与SFINAE: #include <type_traits> template<class T> struct is_template_with_one_param : std::false_type {}; templa
#包括
模板
结构C
{
C(T i)
{
标准::可与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;
}
#包括
模板
结构是带有一个参数的模板
:std::false\u类型
{};
模板
结构是带有一个参数的模板
:std::true\u类型
{};
#包括
模板
typename std::enable_if::type
F(ti)
{
std::cout另一种可能的解决方案:
#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);
}
#包括
模板
结构C
{
C(T i)
{
std::我很惭愧地承认,但我从来都不了解模板参数。最终我放弃了尝试。这归结为这样一个事实:因为函数模板不支持部分专门化,所以在函数模板的情况下,您喜欢的类模板的模式匹配是不存在的。我认为这是可能的使用SFINAE;这两个函数将采用相同的参数,但一个接受非模板类型,而另一个接受模板专门化。经典的方法是将函数转发到结构实现(即:template void F(T){C()(T);}
使用operator()
而不是构造函数)。作为一种算法,重载解析在这里的工作方式没有什么不同,但其输入数据在这两种情况下是不同的。对于明确指定的F(R)
,重载集(=使用名称F
找到的函数,已经对其执行了类型推断和替换)是void F(R);
(即函数void F(R)
带有T=R
)和void F(R);
(函数void F(T)
带有T=R
)。注意,您没有指定参数类型,而是指定模板参数;因此第一个函数成为F(R)
.N.B.其中一个重载也可以写为模板void F(ti,TT…)
这是一个正确的答案。但这是一个解决办法,所以我将等待一段时间,然后再将其标记为正确答案。我想知道是否有一个自然的“一个参数”语法。但恐怕没有。这就是为什么每个人都使用带有静态函数的类模板作为变通方法,这实际上比使用SFINAE更好。@PatrickFromberg,正如Nawaz所说,另一种方法是显式专门化,如模板void F(R)函数模板的部分专门化是不允许的;如果允许的话,可以编写模板void F(TT);
。如问题中所述,类型推断工作正常。问题出现的地方是显式实例化。@Patrick Fromberg:F(r)
和F(4)
也可以工作。
#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);
}
#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);
}