2017-05-27 13 views
6

私はstd :: optionalを使用しようとしていますが、コードのエラーが発生します。
#include <experimental/optional>と指定しました。コンパイラオプションは-std=c++1z,-lc++experimentalです。 の使い方C++でstd :: optionalを使用するにはどうすればよいですか?

次のコードである:

#include <experimental/optional> 
#include <iostream> 

std::experimental::optional<int> my_div(int x, int y) { 
    if (y != 0) { 
     int b = x/y; 
     return {b}; 
    } 
    else { 
     return {}; 
    } 
} 

int main() { 
    auto res = my_div(6, 2); 
    if (res) { 
     int p = res.value(); 
     std::cout << p << std::endl; 
    } 
} 

エラーメッセージ:

optional.cpp:17:21: error: call to unavailable member function 'value': 
     int p = res.value(); 
       ~~~~^~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/experimental/optional:525:17: note: candidate function has been explicitly made unavailable 
    value_type& value() 
       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/experimental/optional:517:33: note: candidate function has been explicitly made unavailable 
    constexpr value_type const& value() const 
           ^
1 error generated. 

OS:MacOSの10.12.5

コンパイラバージョン:

Apple LLVM version 8.1.0 (clang-802.0.42) 
Target: x86_64-apple-darwin16.6.0 
Thread model: posix 
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin 
+2

gcc 6.3.1で問題なくコンパイルできます。おそらく、コンパイラによるC++ 1zサポートのレベルが不十分である可能性があります。 –

+0

申し訳ありませんが、私のクローズアップは時期尚早でした。私は(少なくとも私のMACブックでも、同じコンパイラを実行している)ファイル/ライブラリ/開発者/ CommandLineTools/usr/include/C++/v1/experimental/optional'があることが分かります。しかし残念なことに、エラーメッセージを表示していないので、とにかくこれを閉じる必要があります。 – Walter

+0

@Walterエラーメッセージを追加しました。 – KiYugadgeter

答えて

7

あなたがエラーを投稿した後、私はそれを調べることができました(しかし、あなたはまったく同じことができました)。 SHORT

、IN

これはOSX上で、アップルが提供するようoptionalに問題/バグですが、簡単な回避策があります。

WHAT

ファイル/Library/Developer/CommandLineTools/usr/include/c++/v1/exper‌​imental/optionalが起こっているのは、プリプロセッサだけ(コンパイラオプション-E)を実行している

template <class _Tp> 
class optional 
    : private __optional_storage<_Tp> 
{ 
    /* ... */ 

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS 
    constexpr value_type const& value() const 
    { 
    if (!this->__engaged_) 
     throw bad_optional_access(); 
    return this->__val_; 
    } 

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS 
    value_type& value() 
    { 
    if (!this->__engaged_) 
     throw bad_optional_access(); 
    return this->__val_; 
    } 
    /* ... */ 
}; 

として問題のある機能optional::valueを宣言マクロが

#define _LIBCPP_INLINE_VISIBILITY \ 
    __attribute__ ((__visibility__("hidden"), __always_inline__)) 
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \ 
    __attribute__((unavailable)) 
に展開することが明らかになりました

特に、マクロ_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS

// Define availability macros. 
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE) 
// ... 
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable)) 
// ... 
#else 
// ... 
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS 
// ... 
#endif 

としてファイル/Library/Developer/CommandLineTools/usr/include/c++/v1/__config#define dがこのように、これはLLVMのlibcの++ APIからアップル特定の変更です。マクロの名前が示すように、その理由は、Appleがそれに依存する機能(optional::value)を実装することはできませんので、

class bad_optional_access 
: public std::logic_error 
{ 
public: 
    bad_optional_access() : std::logic_error("Bad optional Access") {} 
    virtual ~bad_optional_access() noexcept; 
}; 

を利用可能にしていないということです。 bad_optional_accessが提供されていない(それによって規格が破られている)理由は不明ですが、ライブラリ(dylib)をbad_optional_access::~bad_optional_access()に変更する必要があります。 AROUND

は単にoptional::operator*代わり

int p = *res; 

唯一の本当の違いは何のアクセスチェックが行われないことであるを使用操作方法

。それが必要な場合は、自分でしてください

template<typename T> 
T& get_value(std::experimental::optional<T> &opt) 
{ 
    if(!opt.has_value()) 
    throw std::logic_error("bad optional access"); 
    return *opt; 
} 

template<typename T> 
T const& get_value(std::experimental::optional<T>const &opt) 
{ 
    if(!opt.has_value()) 
    throw std::logic_error("bad optional access"); 
    return *opt; 
} 
+1

"なぜbad_optional_accessが提供されないのか(それによって標準を破る)は不明ですが、bad_optional_access ::〜bad_optional_access()を含むようにライブラリ(dylib)を変更する必要があるかもしれません。 そうです。将来のOSバージョンでは必要なシンボルが提供され、それ以降のバージョンにデプロイされたアプリケーションはそのシンボルを使用できるようになります。 –

+0

@GregParkerあなたはこの問題に関して権限を持って話しますか?なぜこれを故意に制動してこのように設計したのですか? – Walter

関連する問題