2016-07-26 15 views
1

C++でtype initialisationと一緒にelseを使用するには?

myArbPrec("0.1"); 

を使用して初期化することができるクラス「myArbPrec」を(例えばそれが任意精度のタイプを表す)を考えます。

私のコードはmyArbPrecdoubleの両方と互換性があります。ユーザーはテンプレートを使用して型を設定します。

0.1など、プログラムで使用されるテンプレートクラスにはいくつかの定数があります。これらの定数は、ユーザーが選択するそれぞれのタイプで表されます。

私の質問は、選択したタイプに応じて初期化されるコードに定数を配置するにはどうすればいいですか?具体的には、myArbPrecについては、myArbPrec("0.1")と初期化する必要があります。 doubleの場合は、double(0.1)と初期化する必要があります。

問題は、私がmyArbPrecにのみ、これは潜在的に精度を失って、倍増する最初を変換するので、myArbPrec(0.1)を使用して、できないことです。したがって、テンプレート引数がTの場合、T(0.1)と書くことはできません。しかし、double("0.1")は構文的に正しくないので、T("0.1")も使用できません。 typeid(T) == typeid(double)が作るこれ、常にfalseの場合でも、else分岐がまだコンパイルされているので、

template<typename T> 
T atof(const char * c) { 
    if (typeid(T) == typeid(double)) 
     return std::atof(c); 
    else 
     return T(c); 
} 

しかし、これは失敗します。

はこれまでのところ、私はこのような何かを書くことで、私の問題にthis answerを適応しようとしましたTdoubleであっても失敗します。あなたのatof機能の

+0

を、あなたがC++ 17を楽しみにすることができ、 '場合でconstexpr'は存在するものです。例:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0292r1.html –

答えて

3

使用相互に排他的SFINAEオーバーロード:

namespace foo { 
    template<typename T> 
    typename std::enable_if<std::is_same<T, double>::value, T>::type atof(const char * c) { 
    return std::atof(c); 
    } 

    template<typename T> 
    typename std::enable_if<!std::is_same<T, double>::value, T>::type atof(const char * c) { 
    return T(c); 
    } 
} 
+0

'std :: atof'の使用はAFAIKを無効にし、 'std :: strtof'(または文字列の' std :: stof')をよく使う。 – Superlokkus

+3

@Superlokkus 'std :: atofの使用はAFAIK disencouraged'です:このディスクロージャーを助長するソースを投稿してください。 – 101010

+1

OSX/FreeBSDのマニュアルページ:https://www.freebsd.org/cgi/man.cgi?query=atof&apropos=0&sektion=3&manpath=FreeBSD+10.3-RELEASE+and+Ports&arch=default&format=htmlとオープングループ: http://pubs.opengroup.org/onlinepubs/9699919799/functions/atof.html C標準を読んでいるなら、少なくとも1つの実際の理由を見つけることができます。結果が表現できないときにUBを呼び出します。 st(r)xxファミリー。 – Superlokkus

0

私が思う17 C++とは、あなたがif constexprとあなたの元のテンプレートを使用することができますし、それが働くだろう。

提案された論文はhereです。

これをテストするコンパイラはありません。

+1

http://melpon.org/wandbox/permlink/L8NPsPi4eiKMCeaO – 101010

0

101010 @の提案の代替ソリューションとして、あなたがタグディスパッチとオーバーロードされた関数を使用することができます答えに加えて

#include<type_traits> 
#include<utility> 
#include<cstdlib> 
#include<iostream> 

template<typename> 
struct tag {}; 

double atof(tag<double>, const char *c) { 
    std::cout << "double" << std::endl; 
    return std::atof(c); 
} 

template<typename T> 
T atof(tag<T>, const char * c) { 
    std::cout << "something else" << std::endl; 
    return T{c}; 
} 

template<typename T> 
T atof(const char * c) { 
    return atof(tag<std::decay_t<T>>{}, c); 
} 

int main() { 
    atof<double>("3.1"); 
    atof<std::string>("bar"); 
} 
関連する問題