C++ 不同类型标识符的编译时计数器

C++ 不同类型标识符的编译时计数器,c++,templates,template-meta-programming,C++,Templates,Template Meta Programming,我正在写一些模板元编程代码。出于某些原因,我希望使代码中的每个对象都具有不同的类型。原始代码如下所示: template<unsigned int index> class Class1{ }; template<typename T1, typename T2, unsigned int index> class Class2{ std::tuple<T1*, T2*> v; public: Class2(T1* t1, T2* t2

我正在写一些模板元编程代码。出于某些原因,我希望使代码中的每个对象都具有不同的类型。原始代码如下所示:

template<unsigned int index>
class Class1{

};

template<typename T1, typename T2, unsigned int index>
class Class2{
    std::tuple<T1*, T2*> v;
  public:
    Class2(T1* t1, T2* t2): v(std::tuple<T1*, T2*>(t1, t2)) {}
};

template<unsigned int index>
auto makeClass1() {
    return Class1<index>();
}

template<unsigned int index, typename T1, typename T2>
auto mul(T1& t1, T2& t2) {
    return Class2<T1, T2, index>(&t1, &t2);
}    

int main() {
    auto t1 = makeClass1<0>();  // Type of TT1 is Class1<0>
    auto t2 = makeClass1<1>();  // Type of TT2 is Class1<1>
    auto m1 = mul<0>(t1, t2);
    auto m2 = mul<1>(t1, t2); // Type of m2 is different from type of m1.
}
template<unsigned int index>
class Class1{

};

template<typename T1, typename T2, unsigned int index>
class Class2{
    std::tuple<T1*, T2*> v;
  public:
    Class2(T1* t1, T2* t2): v(std::tuple<T1*, T2*>(t1, t2)) {}
};

template<unsigned int index = IncreaseCounter<?>::value>
auto makeClass1() {
    return Class1<index>();
}

template<unsigned int index = IncreaseCounter<?>::value, typename T1, typename T2>
auto operator*(T1& t1, T2& t2) {
    return Class2<T1, T2, index>(&t1, &t2);
}

int main() {
    auto t1 = makeClass1();  // Type of TT1 is Class1<0>
    auto t2 = makeClass1();  // Type of TT2 is Class1<1>
    auto m1 = t1*t2
    auto m2 = t1*t2; // Type of m2 is different from type of m1.
}
模板
一班{
};
模板
二级{
std::元组v;
公众:
类2(T1*T1,T2*T2):v(std::tuple(T1,T2)){
};
模板
自动生成类1(){
返回Class1();
}
模板
自动多路复用器(T1和T1、T2和T2){
返回类别2(&t1和&t2);
}    
int main(){
auto t1=makeClass1();//TT1的类型为Class1
auto t2=makeClass1();//TT2的类型为Class1
自动m1=mul(t1,t2);
auto m2=mul(t1,t2);//m2的类型不同于m1的类型。
}
这段代码很有用,但我希望我的代码易于使用。所以我想问,有没有什么解决方案可以让代码看起来像这样:

template<unsigned int index>
class Class1{

};

template<typename T1, typename T2, unsigned int index>
class Class2{
    std::tuple<T1*, T2*> v;
  public:
    Class2(T1* t1, T2* t2): v(std::tuple<T1*, T2*>(t1, t2)) {}
};

template<unsigned int index>
auto makeClass1() {
    return Class1<index>();
}

template<unsigned int index, typename T1, typename T2>
auto mul(T1& t1, T2& t2) {
    return Class2<T1, T2, index>(&t1, &t2);
}    

int main() {
    auto t1 = makeClass1<0>();  // Type of TT1 is Class1<0>
    auto t2 = makeClass1<1>();  // Type of TT2 is Class1<1>
    auto m1 = mul<0>(t1, t2);
    auto m2 = mul<1>(t1, t2); // Type of m2 is different from type of m1.
}
template<unsigned int index>
class Class1{

};

template<typename T1, typename T2, unsigned int index>
class Class2{
    std::tuple<T1*, T2*> v;
  public:
    Class2(T1* t1, T2* t2): v(std::tuple<T1*, T2*>(t1, t2)) {}
};

template<unsigned int index = IncreaseCounter<?>::value>
auto makeClass1() {
    return Class1<index>();
}

template<unsigned int index = IncreaseCounter<?>::value, typename T1, typename T2>
auto operator*(T1& t1, T2& t2) {
    return Class2<T1, T2, index>(&t1, &t2);
}

int main() {
    auto t1 = makeClass1();  // Type of TT1 is Class1<0>
    auto t2 = makeClass1();  // Type of TT2 is Class1<1>
    auto m1 = t1*t2
    auto m2 = t1*t2; // Type of m2 is different from type of m1.
}
模板
一班{
};
模板
二级{
std::元组v;
公众:
类2(T1*T1,T2*T2):v(std::tuple(T1,T2)){
};
模板::值,类型名T1,类型名T2>
自动操作员*(T1和T1、T2和T2){
返回类别2(&t1和&t2);
}
int main(){
auto t1=makeClass1();//TT1的类型为Class1
auto t2=makeClass1();//TT2的类型为Class1
自动m1=t1*t2
auto m2=t1*t2;//m2的类型与m1的类型不同。
}
注意:我想我需要一个编译时计数器。但是除了宏解决方案:
\uuuuu计数器
\uuuu行
,我找不到任何其他编译时解决方案。宏解决方案对我的代码无效

除了编译时计数器外,任何其他解决方案都可以


谢谢你阅读我的问题。由于我的英语表达能力差,请容忍我的错误句子。

让我们来看看你问题的核心:

    auto m1 = t1*t2;
    auto m2 = t1*t2; // Type of m2 is different from type of m1.
您有完全相同的表达式(
t1*t2
),但希望此表达式生成两种不同的类型

总的来说,在编译时计算对象的想法是松散的。在这种情况下你会期望什么

    for (int i = 0; i < 10; ++i) {
        auto m = t1*t2;
    }
for(int i=0;i<10;++i){
自动m=t1*t2;
}

回到您的代码:您需要以某种方式引入这个编译时索引,就像您在
mul
中所做的那样:在
mul
中或者在结果类型中(显式类型而不是
auto
+适当的转换)。

让我们来看看您问题的核心:

    auto m1 = t1*t2;
    auto m2 = t1*t2; // Type of m2 is different from type of m1.
您有完全相同的表达式(
t1*t2
),但希望此表达式生成两种不同的类型

总的来说,在编译时计算对象的想法是松散的。在这种情况下你会期望什么

    for (int i = 0; i < 10; ++i) {
        auto m = t1*t2;
    }
for(int i=0;i<10;++i){
自动m=t1*t2;
}

回到您的代码:您需要以某种方式引入这个编译时索引,就像您在
mul
中所做的那样:在
mul
或在结果类型(显式类型而不是
auto
+适当转换)中所做的那样

template <typename = decltype([]{})>
class Class1{};

template<typename T1, typename T2, typename = decltype([]{})>
class Class2{
    std::tuple<T1*, T2*> v;
  public:
    Class2(T1* t1, T2* t2): v(std::tuple<T1*, T2*>(t1, t2)) {}
};

template <typename T = decltype([]{})>
auto makeClass1() { return Class1<T>();}

template<typename T1, typename T2, typename T = decltype([]{})>
auto operator*(T1& t1, T2& t2) {
    return Class2<T1, T2, T>(&t1, &t2);
}

int main() {
    auto t1 = makeClass1();
    auto t2 = makeClass1(); // Type of t2 is different from type of t1.
    auto m1 = t1*t2;
    auto m2 = t1*t2; // Type of m2 is different from type of m1.

    static_assert(!std::is_same_v<decltype(t1), decltype(t2)>);
    static_assert(!std::is_same_v<decltype(m1), decltype(m2)>);
}
模板
类别1{};
模板
二级{
std::元组v;
公众:
类2(T1*T1,T2*T2):v(std::tuple(T1,T2)){
};
模板
自动生成类1(){return Class1();}
模板
自动操作员*(T1和T1、T2和T2){
返回类别2(&t1和&t2);
}
int main(){
auto t1=makeClass1();
auto t2=MakeClas1();//t2的类型与t1的类型不同。
自动m1=t1*t2;
auto m2=t1*t2;//m2的类型与m1的类型不同。
静态断言(!std::is_same_v);
静态断言(!std::is_same_v);
}

在C++20中,您可以执行以下操作:

template <typename = decltype([]{})>
class Class1{};

template<typename T1, typename T2, typename = decltype([]{})>
class Class2{
    std::tuple<T1*, T2*> v;
  public:
    Class2(T1* t1, T2* t2): v(std::tuple<T1*, T2*>(t1, t2)) {}
};

template <typename T = decltype([]{})>
auto makeClass1() { return Class1<T>();}

template<typename T1, typename T2, typename T = decltype([]{})>
auto operator*(T1& t1, T2& t2) {
    return Class2<T1, T2, T>(&t1, &t2);
}

int main() {
    auto t1 = makeClass1();
    auto t2 = makeClass1(); // Type of t2 is different from type of t1.
    auto m1 = t1*t2;
    auto m2 = t1*t2; // Type of m2 is different from type of m1.

    static_assert(!std::is_same_v<decltype(t1), decltype(t2)>);
    static_assert(!std::is_same_v<decltype(m1), decltype(m2)>);
}
模板
类别1{};
模板
二级{
std::元组v;
公众:
类2(T1*T1,T2*T2):v(std::tuple(T1,T2)){
};
模板
自动生成类1(){return Class1();}
模板
自动操作员*(T1和T1、T2和T2){
返回类别2(&t1和&t2);
}
int main(){
auto t1=makeClass1();
auto t2=MakeClas1();//t2的类型与t1的类型不同。
自动m1=t1*t2;
auto m2=t1*t2;//m2的类型与m1的类型不同。
静态断言(!std::is_same_v);
静态断言(!std::is_same_v);
}

.

即使令牌完全相同,我们也可能有不同的返回类型,例如,请参见我的答案。对于循环,我们可能会说它不是一个独特的标识符。感谢您回答这个问题。我以前从未想过这种情况,谢谢提醒。我认为每个循环都会返回不同的类型,但是这个对象在每次循环后都会被销毁,所以像这样的对象不是我的重点。即使令牌完全相同,我们也可能有不同的返回类型,例如,请参见我的答案。对于循环,我们可能会说它不是一个独特的标识符。感谢您回答这个问题。我以前从未想过这种情况,谢谢提醒。我认为每个循环都会返回不同的类型,但是这个对象在每次循环后都会被销毁,所以像这样的对象不是我的重点。这是如何工作的?编译器是否每次访问模板时都实例化一个新类型?标准是否保证
!std::在所有情况下都是相同的吗?每个lambda都有自己的类型,所以是的。(默认模板参数在调用站点实例化)。感谢您回答此问题。您能告诉我C++20中此功能(
[]{}
)的名称吗?我想知道这个特性的更多细节。@Dreamer这只是一个例子,不是特定于C++20的。然而,未赋值上下文中的lambdas是C++20的一个特性<例如,code>decltype([]{})
。这是如何工作的?编译器是否每次访问模板时都实例化一个新类型?标准是否保证
!std::在所有情况下都是相同的吗?每个lambda都有自己的类型,所以是的。(默认模板参数在调用站点实例化)。感谢您回答此问题。您能告诉我C++20中此功能(
[]{}
)的名称吗?我想知道这个特性的更多细节。@Dreamer这只是一个例子,不是特定于C++20的。怎么