वैज्ञानिक कंप्यूटिंग के लिए सी ++ पर a great paper है जहां लेखक (टी। वेल्डुइज़ेन) लक्षण-आधारित पता प्रकार पदोन्नति के लिए दृष्टिकोण सुझाता है। मैं इस तरह के दृष्टिकोण का इस्तेमाल किया है, और यह प्रभावी पाया:Idiomatic C++ 11 प्रकार पदोन्नति
#include<iostream>
#include<complex>
#include<typeinfo>
template<typename T1, typename T2>
struct promote_trait{};
#define DECLARE_PROMOTION(A, B, C) template<> struct promote_trait<A, B> { using T_promote = C;};
DECLARE_PROMOTION(int, char, int);
DECLARE_PROMOTION(int, float, float);
DECLARE_PROMOTION(float, std::complex<float>, std::complex<float>);
// similarly for all possible type combinations...
template<typename T1, typename T2>
void product(T1 a, T2 b) {
using T = typename promote_trait<T1, T2>::T_promote;
T ans = T(a) * T(b);
std::cout<<"received "
<<typeid(T1).name()<<"("<<a<<")"<<" * "
<<typeid(T2).name()<<"("<<b<<")"<<" ==> "
<<"returning "
<<typeid(T).name()<<"("<<ans<<")"<<std::endl;
}
int main() {
product(1, 'a');
product(1, 2.0f);
product(1.0f, std::complex<float>(1.0f, 2.0f));
return 0;
}
आउटपुट:
received i(1) * c(a) ==> returning i(97)
received i(1) * f(2) ==> returning f(2)
received f(1) * St7complexIfE((1,2)) ==> returning St7complexIfE((1,2))
प्रकार typeinfo द्वारा लौटाए के नाम कार्यान्वयन निर्भर है; अपने उत्पादन मेरा है, जो ओएस पर जीसीसी 4.7.2 इस्तेमाल किया से अलग हो सकता एक्स 10.7.4
संक्षेप में, दृष्टिकोण एक promote_trait
जो केवल एक प्रकार परिभाषा में शामिल है परिभाषित करता है: प्रकार है जो दो प्रकार जब ऑपरेटिंग बढ़ावा दिया जाना चाहिए करने के लिए एक दिए गए तरीके से। किसी को सभी संभावित प्रचार घोषित करने की आवश्यकता है।
एक समारोह दोनों प्रकार प्राप्त करता है, यह promote_trait
पर निर्भर करता है सही, परिणाम की पदोन्नत प्रकार निकालना। यदि किसी दिए गए जोड़ी के लिए कोई विशेषता परिभाषित नहीं की गई है तो कोड संकलित करने में विफल रहता है (एक वांछनीय विशेषता)।
अब प्रश्न में पेपर 2000 में लिखा गया था, और हम जानते हैं कि सी ++ पिछले दशक में नाटकीय रूप से विकसित हुआ है।
वहाँ लक्षण आधारित दृष्टिकोण Veldhuizen द्वारा शुरू के रूप में प्रभावी प्रकार पदोन्नति के साथ काम करने के लिए एक आधुनिक, मुहावरेदार सी ++ 11 दृष्टिकोण है: मेरा प्रश्न है, तो, निम्नलिखित है?
#include<iostream>
#include<complex>
#include<typeinfo>
#include<typeindex>
#include<string>
#include<utility>
#include<map>
// a map to homogenize the type names across platforms
std::map<std::type_index, std::string> type_names = {
{typeid(char) , "char"},
{typeid(int) , "int"},
{typeid(float) , "float"},
{typeid(double) , "double"},
{typeid(std::complex<int>) , "complex<int>"},
{typeid(std::complex<float>) , "complex<float>"},
{typeid(std::complex<double>) , "complex<double>"},
};
template<typename T1, typename T2>
void promotion(T1 a, T2 b) {
std::string T1name = type_names[typeid(T1)];
std::string T2name = type_names[typeid(T2)];
std::string TPname = type_names[typeid(typename std::common_type<T1, T2>::type)];
std::cout<<T1name<<"("<<a<<") and "<<T2name<<"("<<b<<") promoted to "<<TPname<<std::endl;
}
int main() {
promotion(1, 'a');
promotion(1, 1.0);
promotion(1.0, 1);
promotion(std::complex<double>(1), 1);
promotion(1.0f, 1);
promotion(1.0f, 1.0);
promotion(std::complex<int>(1), std::complex<double>(1));
promotion(std::complex<double>(1), std::complex<int>(1));
promotion(std::complex<float>(0, 2.0f), std::complex<int>(1));
return 0;
}
उत्पादन के साथ :
int(1) and char(a) promoted to int
int(1) and double(1) promoted to double
double(1) and int(1) promoted to double
complex<double>((1,0)) and int(1) promoted to complex<double>
float(1) and int(1) promoted to float
float(1) and double(1) promoted to double
complex<int>((1,0)) and complex<double>((1,0)) promoted to complex<int>
complex<double>((1,0)) and complex<int>((1,0)) promoted to complex<int>
complex<float>((0,2)) and complex<int>((1,0)) promoted to complex<int>
मैं हैरान हूं
(std::common_type
के प्रयोग पर) संपादन
ल्यूक डेंटन के सुझाव के आधार पर, मैं निम्नलिखित कोड जो std::common_type
का उपयोग करता है बनाया यह ध्यान देने के लिए कि पिछले तीन प्रचारों के अलावा सभी की अपेक्षा है। complex<int>
और complex<double>
या complex<float>
को complex<int>
पर प्रचारित क्यों किया जाएगा!
आप 'std :: common_type' से परिचित हैं? –
@ ल्यूकडैंटन: बहुत, बहुत उपयोगी। मैं हैरान हूं, तथापि, 'std :: जटिल' और 'std :: जटिल ' और 'std :: जटिल ' के बीच प्रकार पदोन्नति के बारे में। कोई अंतर्दृष्टि? –
Escualo
यह शायद 'std :: complex' के प्राथमिक टेम्पलेट की वजह से है, और की बात:", डबल या लंबी डबल नाव के अलावा अन्य, किसी भी प्रकार के लिए टेम्पलेट जटिल instantiating के प्रभाव अनिर्दिष्ट है। " –