Visual C++ 2015では、C++11の属性構文とC++14のdeprecatedとnoreturnの属性に対応しています。すると気になるのがViusal C++がもともと持っていた属性構文との互換性です。

代わりになるのかどうか、まずはC++/CLIやC++/CXで試してみました。先に言ってしまうと、結果はダメでした。

1つ目として、main関数においてCOMのアパートメントを指定するSystem::STAThreadAttribute属性およびPlatform::STAThreadAttribute属性を試しました。

まず、C++/CLIのコードです。

// cl /clr a.cpp ole32.lib
#include <iostream>
#include <windows.h>
 
using namespace std;
using namespace System;
 
//[[STAThread]]
[STAThread]
int main()
{
    APTTYPE aptType;
    APTTYPEQUALIFIER aptQualifier;
    auto hr = CoGetApartmentType(&aptType, &aptQualifier);
    if (SUCCEEDED(hr))
    {
        cout << boolalpha;
        cout << (aptType == APTTYPE_MAINSTA) << endl;
        cout << (aptType == APTTYPE_STA) << endl;
    }
    else
    {
        cout << "CoGetApartmentType failed: " << showbase << hex << hr << endl;
    }
}

[STAThread]だと「true false」という出力で、メインSTAになっている結果です。一方、[[STAThread]]だと「false false」で、MTA(.NET Frameworkのデフォルト)のようです。

次に、C++/CXのコードです。

// cl /ZW b.cpp
 
#include <iostream>
#include <windows.h>
 
using namespace std;
using namespace Platform;
 
//[[STAThread]]
[STAThread]
int main()
{
    APTTYPE aptType;
    APTTYPEQUALIFIER aptQualifier;
    auto hr = CoGetApartmentType(&aptType, &aptQualifier);
    if (SUCCEEDED(hr))
    {
        cout << boolalpha;
        cout << (aptType == APTTYPE_MAINSTA) << endl;
        cout << (aptType == APTTYPE_STA) << endl;
    }
    else
    {
        cout << "CoGetApartmentType failed: " << showbase << hex << hr << endl;
    }
}

これも、[STAThread]だと出力は「true false」で、メインSTAになっています。一方、[[STAThread]]だと出力は「CoGetApartmentType failed: 0x800401f0」です。これはCO_E_NOTINITIALIZED、すなわちCOMの初期化がされていない状態です。

もう1つ試してみました。System::FlagsAttribute属性およびPlatform::Metadata::FlagsAttribute属性です。

こちらも、まずはC++/CLIのコードです。

using namespace System;
 
[Flags]
public enum class Hoge1 : unsigned
{
    Foo = 0,
    Bar = 1,
};
 
public enum class [[Flags]] Hoge2 : unsigned
{
    Foo = 0,
    Bar = 1,
};
 
void f()
{
    auto a = Hoge1::Foo | Hoge1::Bar;
    auto b = Hoge2::Foo | Hoge2::Bar;
}

そして、C++/CXのコードです。

using namespace Platform::Metadata;
 
namespace Hoge
{
    [Flags]
    public enum class Hoge1 : unsigned
    {
        Foo = 0,
        Bar = 1,
    };
 
    public enum class [[Flags]] Hoge2 : unsigned
    {
        Foo = 0,
        Bar = 1,
    };
 
    void f()
    {
        auto a = Hoge1::Foo | Hoge1::Bar;
        auto b = Hoge2::Foo | Hoge2::Bar;
    }
}

何回かコンパイルを試した結果、「そうか、C++の属性はVC++のと指定する位置が異なるんだな」ということを知りました。それはともかく、やっぱり[[Flags]]を使うHoge2はC++/CLIでもC++/CXでもダメでした。

というわけで、「C++/CLIおよびC++/CXでは、以前からある属性構文とC++11の属性構文とは別物である。互換ではないことが分かった」というお話でした。

2015年10月17日追記:FlagsのサンプルコードがC++/CLIとC++/CXで逆でしたので、掲載順序を直しました。


スポンサード リンク

この記事のカテゴリ

  • ⇒ C++11の属性とC++/CLIとC++/CX
  • ⇒ C++11の属性とC++/CLIとC++/CX