web-dev-qa-db-ja.com

「自動」型推論の使用-コンパイラがどの型を推論したかを調べる方法は?

autoキーワードの使用時にコンパイラがどのタイプを推測したかを知るにはどうすればよいですか?

例1:よりシンプル

auto tickTime = 0.001;

これはfloatまたはdouble?として推定されましたか

例2:より複雑な(そして現在の頭痛):

typedef std::ratio<1, 1> sec;
std::chrono::duration<double, sec > timePerTick2{0.001};
 auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2;

nextTickTimeとはどのタイプですか?

私が抱えている問題は、nextTickTimestd::coutに送信しようとしたときです。次のエラーが表示されます。

./main.cpp: In function ‘int main(int, char**)’:
./main.cpp:143:16: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
  std::cout << std::setprecision(12) << nextTickTime << std::endl; // time in seconds
            ^
In file included from /usr/include/c++/4.8.2/iostream:39:0,
             from ./main.cpp:10:
/usr/include/c++/4.8.2/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<double, std::ratio<1l, 1000000000l> > >]’
 operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
69
kmiklas

Effective Modern C++のアイデアを使用します。これは、実装されていないテンプレートを使用します。タイプはコンパイラエラーで出力されます。

 template<typename T> struct TD;

自動変数varについて、その定義の後に以下を追加します。

 TD<decltype(var)> td;

コンパイラのエラーメッセージを見ると、varのタイプが含まれています。

101
marcinj

事前のヘルパー定義を必要としないlo-fiトリックは次のとおりです。

typename decltype(nextTickTime)::_

コンパイラは、_は、nextTickTime型のメンバーではありません。

26
John McFarlane

実行時にboost::core::demangleを使用して型名を取得するtypeidバージョンは次のとおりです。

#include <string>
#include <iostream>
#include <typeinfo>
#include <vector>
using namespace std::literals;

#include <boost/core/demangle.hpp>

template<typename T>
std::string type_str(){ return boost::core::demangle(typeid(T).name()); }

auto main() -> int{
    auto make_vector = [](auto head, auto ... tail) -> std::vector<decltype(head)>{
        return {head, tail...};
    };

    auto i = 1;
    auto f = 1.f;
    auto d = 1.0;
    auto s = "1.0"s;
    auto v = make_vector(1, 2, 3, 4, 5);

    std::cout
    << "typeof(i) = " << type_str<decltype(i)>() << '\n'
    << "typeof(f) = " << type_str<decltype(f)>() << '\n'
    << "typeof(d) = " << type_str<decltype(d)>() << '\n'
    << "typeof(s) = " << type_str<decltype(s)>() << '\n'
    << "typeof(v) = " << type_str<decltype(v)>() << '\n'
    << std::endl;
}

これは私のシステムでこれを印刷します:

typeof(i) = int
typeof(f) = float
typeof(d) = double
typeof(s) = std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
typeof(v) = std::vector<int, std::allocator<int> >
8
CoffeeandCode

typeidは、ほとんどの場合変数の型を取得するために使用できます。それはコンパイラに依存しており、奇妙な結果をもたらすのを見てきました。 g ++のデフォルトではRTTIがオンになっていますが、Windows側ではわかりません。

#include <iostream>
#include <typeinfo>
#include <stdint.h>
#include <chrono>
#include <ctime>

typedef std::ratio<1, 1> sec;
int main()
{
    auto tickTime = .001;
    std::chrono::duration<double, sec > timePerTick2{0.001};
    auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2;
    std::cout << typeid(tickTime).name() << std::endl;
    std::cout << typeid(nextTickTime).name() << std::endl;

    return 0;
}

./a.out | c++filt

double
std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >
5
Matthew Fisher

Daniel Jour のように、エラーメッセージを読みます。

... _Tp = std::chrono::time_point<
           std::chrono::_V2::system_clock,
           std::chrono::duration<
             double, std::ratio<1l, 1000000000l> > > ...
3
Jacob Krall

コンパイラによって推定されるタイプは、エラーメッセージにあります。

/usr/include/c++/4.8.2/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>;
 _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<double, std::ratio<1l, 1000000000l> > >]’
  ^^   <-------- the long type name --------------------------------------------------------------------------------------->

複雑な型名ですが、エラーメッセージにあります。

2
R Sahu

This SO answer は、型の名前を印刷するためのNice関数を提供します(実際にはいくつかの実装)。

さらに、この 無料、オープンソース、ヘッダーのみのライブラリ は、chrono::durationsの値およびtypeを印刷するための素晴らしい方法を提供します。

これら2つのユーティリティを組み合わせる:

#include "chrono_io.h"
#include "type_name.h"
#include <iomanip>
#include <iostream>

int
main()
{
    using namespace date;
    typedef std::ratio<1, 1> sec;
    std::chrono::duration<double, sec > timePerTick2{0.001};
    auto nextTickTime = std::chrono::high_resolution_clock::now() + timePerTick2;
    std::cout << type_name<decltype(nextTickTime)>() << '\n';
    std::cout << std::setprecision(12) << nextTickTime.time_since_Epoch() << '\n';
}

私のためのこの出力:

std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<double, std::__1::ratio<1, 1000000000> > >
4.8530542088e+14ns
2
Howard Hinnant

ローテクの解決策は、マウスをnextTickTimeの上に置くことです。これは、一部のGUIでは.nextTickTimecoutの後、適切な外観の値または関数を選択します。

一般的に、あなたがknowを取得した場合、do n't knowを使用しない場合はautoを使用します。これは直感的なビットカウンターです。

そのため、インターレータがautoを使用して呪文を減らすことがわかっている場合、結果が何らかのunknownタイプの場合は、使用する前にそれが何であるかを知る必要がありますauto

Herb、Andrei、およびScottがautoについて議論しています も参照してください。

2
Surt

コンパイルエラーを強制する方法を次に示します。これは、tickTimeのタイプを示しています。

struct {} baD = tickTime;
1
pts

補足として、nextTickTimeの値を効果的に出力するには、適切な std::chrono::duration および duration::count

using std::chrono::duration_cast;
using std::chrono::seconds;

auto baseTime = ...;
std::cout << std::setprecision(12) << duration_cast<seconds>(nextTickTime - baseTime).count()
    << std::endl; // time in seconds
1
oldrinb