वर्तमान में मेरे पास एक टेम्पलेट फ़ंक्शन है जो संकलक तर्क के रूप में स्थिर सरणी और पॉइंटर्स (सामान्य प्रकार के) के लिए TI घटा सकता है:

template<typename TI, typename TO>
inline void foo(const TI a[4], TO b[][3]) { /* works for static arrays and pointers */ }

हालाँकि, अब मुझे 4 सदस्यों x, y, z और w के साथ एक संरचना प्रकार के लिए समान कार्य करने की आवश्यकता है, जो पुराने सरणी पर समान 4 आइटम का प्रतिनिधित्व करता है- प्रकार।

लेकिन मैं यह नहीं कर सकता:

template<typename TI, typename TO>
inline void foo(const TI a[4], TO b[][3]) { /* static arrays and pointer */ }


template<typename TI, typename TO>
inline void foo(const TI a, TO b[][3]) { /* structs */ }

यदि मैं पहले फ़ंक्शन के लिए एक अतिरिक्त पैरामीटर size निर्दिष्ट करता हूं, तो पॉइंटर्स तर्क नीचे दिए गए फ़ंक्शन पर समाप्त होते हैं, और कंपाइलर एक त्रुटि उठाता है क्योंकि पॉइंटर्स में आवश्यक संरचना सदस्य नहीं होते हैं।

मैं एक विशिष्ट प्रकार की संरचना के लिए विशेषज्ञ नहीं हो सकता, क्योंकि अब हम कई प्रकारों का उपयोग करते हैं (अलग-अलग आंतरिक सदस्य प्रकार के double, float, int, आदि)


एमआरई:

#include <cassert>
#include <iostream>
 
template <typename TI, typename TO>
inline
void foo(const TI q[4], TO a[][3])
{
    std::cout << "Method 1\n";
    a[0][0] = a[0][1] = a[0][2] = q[0] + q[1];
    a[1][0] = a[1][1] = a[1][2] = q[1] + q[2];
    a[2][0] = a[2][1] = a[2][2] = q[2] + q[3];
}
 
template <class QT, typename TO>
inline
void foo(const QT q, TO a[][3])
{
    std::cout << "Method 2\n";
    a[0][0] = a[0][1] = a[0][2] = q.x + q.y;
    a[1][0] = a[1][1] = a[1][2] = q.y + q.z;
    a[2][0] = a[2][1] = a[2][2] = q.z + q.w;
}
 
typedef struct {
    float x, y, z, w;
} float4;
 
int main() {
 
    float q1[4] = {1, 2, 3, 4};
    float4 q2 = {1, 2, 3, 4};
    float *q3 = new float[4];
    q3[0] = 1; q3[1] = 2; q3[2] = 3; q3[3] = 4;
    
    float a[3][3], b[3][3], c[3][3];
    
    foo(q1, a);
    foo(q2, b);
    foo(q3, c);
    
    for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
            {
                assert(a[i][j] == b[i][j]);
                assert(b[i][j] == c[i][j]);
            }
}

संकलक त्रुटि:

teste.cpp:19:36: error: member reference base type 'float *const' is not a structure or
      union
    a[0][0] = a[0][1] = a[0][2] = q.x + q.y;
                                  ~^~
teste.cpp:37:5: note: in instantiation of function template specialization
      'foo<float *, float>' requested here
    foo(q1, a);
    ^
teste.cpp:20:36: error: member reference base type 'float *const' is not a structure or
      union
    a[1][0] = a[1][1] = a[1][2] = q.y + q.z;
                                  ~^~
teste.cpp:21:36: error: member reference base type 'float *const' is not a structure or
      union
    a[2][0] = a[2][1] = a[2][2] = q.z + q.w;
                                  ~^~
3 errors generated.
1
648trindade 31 अगस्त 2020, 18:25

1 उत्तर

सबसे बढ़िया उत्तर

आप क्या कर सकते हैं सी ++ 11 से उपलब्ध प्रकार के लक्षणों का उपयोग करना

आप संरचनाओं के लिए समर्पित अपना कार्य निम्नानुसार घोषित कर सकते हैं:

#include <type_traits>

template <class QT, typename TO, std::enable_if_t<std::is_class<QT>::value, int> = 0>
inline
void foo(const QT q, TO a[][3])
{
    std::cout << "Method 2\n";
    a[0][0] = a[0][1] = a[0][2] = q.x + q.y;
    a[1][0] = a[1][1] = a[1][2] = q.y + q.z;
    a[2][0] = a[2][1] = a[2][2] = q.z + q.w;
}

यह संकलक को संरचनाओं और कक्षाओं के लिए इस टेम्पलेट का चयन करने देगा, लेकिन दूसरों के लिए नहीं। इसे तथाकथित SFINAE तकनीक कहा जाता है।

3
rhaport 31 अगस्त 2020, 19:18