2016-10-27 3 views
1

Als Lernprojekt schreibe ich meine eigene Vorlage metaprogramming static_assert. Ich habe online einen Metaprogrammierungstrick gefunden: versuche ein Array der Größe 0 zu erstellen, das nicht kompiliert werden kann. Also verwende ich zwei nahezu identische Ansätze: In Visual Studio funktioniert einer und der andere nicht, aber ich verstehe nicht, was der Unterschied ist. Auf g ++ 5.4.0 funktioniert das nicht (nicht einmal mit dem Flag "-std = C++ 14"). Warum nicht?C++ implementiere meine eigene static_asset

//This correctly aborts the compile on Visual Studio 2015. 
//But on g++ it doesn't work (not even with the "-std=c++14" flag) . 
template <bool b> 
inline void my_static_assert_function() 
{ 
    char member[b]; //if b is false, this is 0-length and fails to compile. 
} 

//On Visual Studio 2015, this does give a warning, but does not 
//abort the compile. Why not? It seems virtually identical to the 
//previous one. And on g++, it doesn't even warn. 
template <bool b> 
struct my_static_assert_struct 
{ 
    char member[b]; //if b is false, this *warns* but compiles. 
}; 

int main() 
{ 
    my_static_assert_function<1 == 2>(); //This aborts the compile, great. 
    my_static_assert_struct<1 == 2> c; //This does NOT abort the compile??? 
} 

Frage # 1 - warum nicht "g ++ -std = C++ 14 main.cpp" erlaubt dies, ohne auch nur eine Warnung zu kompilieren? Sollte da nicht die my_static_assert_function funktionieren? Ich benutze 5.4.0 für Ubuntu.

Frage 2 - auf Visual Studio 2015, My_static_assert_function nicht kompilieren, aber my_static_assert_struct kompiliert mit einer bloßen Warnung. Aber was ist der Unterschied? Wie kann man arbeiten, wenn der andere nicht?

+0

GCC ist ein heikles Tier. Sie müssen wirklich alle seine Flaggen lernen, um es in einen ehrlichen Compiler zu verwandeln. –

+4

(Deshalb machen echte Programmierer Arrays der Größe -1.) –

+0

@Kerrek SB: Bis GCC findet einen Grund, in einer Erweiterung auch zu machen. – AnT

Antwort

1

Wie von @Kerrek SB in den Kommentaren erwähnt, verwendet gcc einige Nicht-Standard-ISO C++ - Erweiterung für Arrays von null Größe zuzulassen, obwohl es Ihnen eine Warnung gibt. Eine weitaus elegantere Alternative ist false über std::enable_ifSFINAE aus, wie so

#include <iostream> 
#include <type_traits> 

template<bool b, typename std::enable_if<b>::type* = nullptr> 
void my_static_assert() 
{ 
    std::cout << "Assertion OK\n"; 
} 

int main() 
{ 
    my_static_assert < (1 < 2) >(); // ok 
    //my_static_assert < (1 > 2) >(); // fails to compile 
} 

Live on Coliru

Eine weitere Alternative (ich glaube, zuerst von vorgeschlagen) ist eine generische Vorlage nicht definiert zu verlassen, und definieren nur die true Spezialisierung. Wenn Sie dann versuchen, die false-Spezialisierung instanziieren, erhalten Sie einen Kompilierungsfehler, da Sie einen unvollständigen Typ nicht instanziieren können. Beispiel unten:

template<bool> // generic 
struct my_static_assert; 

template<> 
struct my_static_assert<true>{}; 

int main() 
{ 
    my_static_assert < (1 < 2) >{}; // ok 
    my_static_assert < (1 > 2) >{}; // fails to compile 
} 

Live on Coliru

Verwandte Themen