我有一个带有 2 个参数的模板。对于第一个参数的某个值,我知道第二个参数应该是什么。我希望我的模板只有一个完整定义(带有 2 个参数的定义),并且能够仅提供一个参数来实例化我的模板。
在下面的例子中,我知道如果第一个模板参数是Foo1
, 第二个应该是 Foo2
.我希望能够创建一个 Someclass<Foo1,Foo2>
通过写作 Someclass<Foo1>
.
#include <iostream>
using namespace std;
struct Foo1 { Foo1() { cout << "Foo1 "; }};
struct Foo2 { Foo2() { cout << "Foo2 "; }};
template <typename ...Dummy> struct SomeClass;
template <typename T, typename U> struct SomeClass<T,U> {
SomeClass() {
T t;
U u;
}
};
/* Here, some one-argument specialization where if SomeClass<Foo1> is desired,
* SomeClass<Foo1, Foo2> is obtained. */
int main() {
SomeClass<Foo1, Foo2> c; //prints "Foo1 Foo2 "
SomeClass<Foo1> c2; //Should print the same thing, right now "incomplete type"
}
我想我将不得不做一个带有两个参数的特化,第一个是 Foo1
,像这样:
template <typename U> struct SomeClass<Foo1, U> {
SomeClass() {
Foo1 f;
U u;
}
};
但是我如何做一个只接受一个参数的特化 Foo1
结果是 SomeClass<Foo1,Foo2>
?
最佳答案
template <>
struct SomeClass<Foo1>:
SomeClass<Foo1,Foo2>
{};
这将处理您描述的 90% 的问题。如果您需要 SomeClass<Foo1>
与 SomeClass<Foo1,Foo2>
相同而不是继承自 ::type
,则您必须编写一堆别名和 Helper
噪音。
template<class...Args>
struct Real;
template<class...Args>
struct Helper {
using type=Real<Args...>;
};
template<class...Args>
using Fake = typename Helper<Args...>::type;
这 3 层是噪音。
::type
让您重新定义参数的含义。
template <typename T, typename U>
struct Real<T,U> {
Real() {
T t;
U u;
}
};
template<>
struct Helper<Foo1>:Helper<Foo1, Foo2> {};
我们从这里的 Helper<Foo1, Foo2>
得到 Fake
。 Helper<Foo1>
没有看到中间的 Fake<Foo1>
,所以我们从 Real<Foo1, Foo2>
得到的类型是 std::is_same< Fake<Foo1>, Fake<Foo1, Foo2> >
,而不是派生类。
这确保了 Fake
。
Helper
是用户使用的别名模板“API”。 Real
允许您进行一些专门化,以根据传入的参数选择要实例化的 ojit_code 模板。
关于c++ - 为单参数模板调用的特定值调用具有更多参数的调用模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59360462/