考虑一个模板类:
template <class First, class Second, class Third, class Fourth>
class MyClass;
为某些模板参数集添加成员函数的正确方法是什么?
例如,当f()
为Second
时,如何添加成员std::string()
?
这是我发现的方法,我传统上使用:
#include <iostream>
#include <type_traits>
#include <array>
template <class Container>
struct Array
{
Container data;
template <class... Dummy,
class = typename std::enable_if<sizeof...(Dummy) == 0>::type,
class = typename std::enable_if<
std::tuple_size<
typename std::conditional<sizeof...(Dummy),
Container,
Container
>::type
>::value == 1
>::type
>
inline typename Container::value_type& value(Dummy...)
{return data[0];}
};
int main()
{
Array<std::array<double, 0>> array0; // Does not have the value() member
Array<std::array<double, 1>> array1; // Have the value() member
Array<std::array<double, 2>> array2; // Does not have the value() member
Array<std::array<double, 3>> array3; // Does not have the value() member
}
它运作良好,但它更像是一种元编程技巧,而不是干净/标准的方法。
答案 0 :(得分:4)
您可以使用继承和专业化。 类似的东西:
template <typename T> struct Helper2 {};
template <> struct Helper2<std::string>
{
void f() {};
};
template <class First, class Second, class Third, class Fourth>
struct MyClass : public Helper2<Second>
{
// Normal code.
};
int main()
{
MyClass<std::string, int, std::string, std::string> c1;
MyClass<int, std::string, int, int> c2;
//c1.f(); // this is an error
c2.f(); // this works
return 0;
}
答案 1 :(得分:1)
我在宣言中并没有达到Dummy
的目的。可以使用功能参数列表中根本未使用的两个默认模板参数来完成:
#include <type_traits>
#include <string>
template <class First> // arguments ommited for brevity
struct MyClass {
template<
typename U = First,
typename = typename std::enable_if< std::is_same<U, std::string>::value >::type
>
void f() {}
};
int main()
{
MyClass<int> c1;
MyClass<std::string> c2;
// this is an error
// c1.f();
c2.f(); // this works
}
请注意,可以作弊:c1.f<std::string>();
仍然有效。
答案 2 :(得分:0)
在C ++ 1y概念TS中,我们有requires
个子句,可以让你轻松完成。见http://isocpp.org/files/papers/n3929.pdf - 但我可能错了。
在C ++之外,你的技术会使你的程序格式错误而不需要诊断,因为所有函数template
s 必须至少有一个有效的特化。实际上,这是一个非常罕见的强制要求,因为在一般情况下解决“没有有效的专业化”涉及解决暂停问题。尽管如此,程序员有责任确保所有template
函数至少有一组有效的template
参数。
我发现在C ++ 11中对零参数函数严格合法的方法是使用基于CRTP的类特化,它消除了CRTP基础专业化中的方法。
另一种方法是创建一个私有的,不可访问的类型,并使其成为在您要禁用它的情况下创建合法专业化的唯一方法。然后在课堂上私下你可以作弊,但在外面你不能作弊。