質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1793閲覧

MSVC?のconstexprの挙動について

aptx42

総合スコア8

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/08/28 12:14

編集2019/08/29 14:24

constexprの挙動について

Visual Studio 2019を用いてenumを管理するようなプログラムをC++14で書いたのですが、constexprとそうでないものの結果が異なり困っています。なお、Wandboxを使ってGCCとClangで試してみたところ、結果は同じ(どちらも1)でした。
実行時のデバッグでは正しい値が帰ってくるのですが、肝心なコンパイル時にどういう挙動をしているかをのぞけないため、解決できずに質問した次第です。
解決策等ご教示いただけると幸いです。

該当のソースコード

タイムアウトしたためリンクが変更されています。また、期間を延ばしました
*** ヘッダファイル側:Pastebin ***

cpp

1enum class test 2{ 3 v0, v1, v2, v4 = 4, v8 = 8, v16 = 16, v32 = 32 4}; 5ENUM2_ENUM(test) 6constexpr inline decltype(auto) get_flags(test) noexcept 7{ 8 using enum2::blk; 9 return enum2::blk_cat( 10 blk(test::v1, 100, test::v2, test::v4, test::v32), //test::v1とtest::v2,test::v4,test::v32は共存できない 11 blk(enum2::force_or(test::v2, test::v4), 100, false, test::v8),//test::v2とtest::test::v4はtest::v8と共存できない 12 blk(enum2::force_or(test::v16, test::v2), 100, test::v32) //(test::v16|test::v2)はtest::v32とは共存できない 13 ); 14} 15#include <iostream> 16 17int main() 18{ 19 constexpr test v0 = test::v0 | test::v1 | test::v2; //3 20 test v1 = test::v0 | test::v1 | test::v2; //1 21 22 std::cout << static_cast<int>(v0) << static_cast<int>(v1); 23 24 return 0; 25}
MSVCの情報

Microsoft Visual Studio Community 2019
Version 16.2.3
VisualStudio.16.Release/16.2.3+29215.179
Microsoft .NET Framework
Version 4.7.03062

インストールされているバージョン:Community

Visual C++ 2019 00435-60000-00000-AA041
Microsoft Visual C++ 2019
(以下略)

###追記
「結果が異なる」のはconstexpr側では結果が3、そうでない側では1(意図した結果)になります。
###追記2
pastebinのリンクがタイムアウトしてしまった(一日経過してしまった)ので更新しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/08/28 12:33

どういうふうに結果が違うんでしょうか
aptx42

2019/08/28 12:39

ご返信ありがとうございます。 constexpr側では結果が3、そうでない側では1(意図した結果)になります。(コメントにてうっすら書いたのですが、わかりにくくて申し訳ないです)
SHOMI

2019/08/28 15:37 編集

constexpr test_holder v0 = test::v0 | test::v1 | test::v2; とするとtest::v1になりますね… (追記) すみません、IntelliSense上ではtest::v1になっていましたが、実際は3でした…
aptx42

2019/08/29 06:12

検証感謝いたします。こちらの環境もIntelliSenseは正しい値を認識できているのですがうーん
guest

回答2

0

自己解決

バグレポ(クソ英語注意)コンパイル時にSwallowを正しく評価できないMSVCのバグだったようです。お騒がせしました

投稿2020/02/14 14:46

aptx42

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

たぶんtest v0 =ではなくtest_holder v0 =としないといけないと思います。

c++

1 constexpr auto v0 = test::v0 | test::v1 | test::v2; //3 2 auto v1 = test::v0 | test::v1 | test::v2; //1

と、autoで推論させると、v0とv1はtest_holderになります。
こうすると結果は共に「1」になります。

投稿2019/09/05 09:04

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aptx42

2019/09/06 09:31

回答ありがとうございます。autoで型推論(=test_holder)にすると出力結果が1になるのは、おそらくholderにoperator bool()が定義されているためです。実際 ```c++ auto kx = (test::v1 | test::v8) & test::v8; std::cout << static_cast<int>(kx); ``` こういうコードを書くと出力は1(8!=0であるから)となります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問