Visual Studio C++ "if constexpr"

Started by
7 comments, last by Hypersomnia 6 years, 10 months ago

I just upgraded to Visual Studio 2017, because I wanted to use "if constexpr" in my code. It seems like it's not supported: If I just do something like "if constexpr(true)", I get an error of "expected a '('"

Does anyone have experience with this? Is there some setting I need to flip to get C++17 compilation enabled? I didn't see anything in the project settings...

Advertisement

Yep, there's a setting for C++17. Its in your project under C/C++ => Language => C++ Language Standard => /std:c++latest. Pardon if the descripting is not accurate, I'm translating from a german VS, but you should be able to find it :) Not sure if this exact feature is already supported even with that switch, let me know if thats the case because this sure sounds like an interesting feature that I somehow completely missed.

I had found that and tried it, but I figured it was just deciding which version of the standard library to include. It doesn't make a difference for this, I still get a compiler error like it can't understand "if constexpr".

That means its most likely not implemented yet in VS2017 - the setting should be right:

https://blogs.msdn.microsoft.com/vcblog/2016/06/07/standards-version-switches-in-the-compiler/

Actually thats really sad, if constexpr on closer look could make my own template code a lot easier :D Well, have to wait it seems...

That's the conclusion I'm coming to as well, and upon further review you are correct about using /std:c++latest.

Ah well, thanks for the help!

It looks like it's available in VS2017 preview 3

No idea when it will make it into the production version, though.

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

It looks like it's available in VS2017 preview 3
No idea when it will make it into the production version, though.


I'm not sure that Preview has it yet - looks like its "15.3 Preview" and not Preview 3, and the [P2] footnote says it will be added in Preview 2... Maybe I'm mistaken m, going to test it and see if it works once I'm home.
This "non-authorative de-facto standard" page says "No":
http://en.cppreference.com/w/cpp/compiler_support

So... might be a feature in a preview version, but not the official one.

Until this feature becomes available, I take advantage of such a trick:


#include <type_traits>
#include <iostream>
using namespace std;

template <bool>
struct constexpr_if;

template <>
struct constexpr_if<true> {
	struct elser {
		template <
			class F,
			class... Args
		> 
		void _else(F&&, Args&&...) {

		}

		template <
			bool C,
			class F,
			class... Args
		> 
		auto _else_if(F&&, Args&&...) {
			return elser();
		}
	};

	template <
		class F,
		class... Args
	>
	auto operator()(F&& callback, Args&&... args) {
		callback(std::forward<Args>(args)...);
		return elser();
	}
};

template <>
struct constexpr_if<false> {
	struct elser {
		template <
			bool C,
			class F,
			class... Args
		>
		auto _else_if(F&& callback, Args&&... args) {
			return constexpr_if<C>()(std::forward<F>(callback), std::forward<Args>(args)...);
		}

		template <
			class F,
			class... Args
		>
		void _else(F&& callback, Args&&... args) {
			callback(std::forward<Args>(args)...);
		}
	};

	template <
		class F,
		class... Args
	>
	auto operator()(F&& callback, Args&&... args) {
		return elser();
	}
};

int main() {
	constexpr_if<true>()(
		[](auto...){
			cout << "1 ";
		}
	)._else_if<true>(
		[](auto...){
			static_assert(false, "Error");
		}
	)._else(
		[](auto...){
			static_assert(false, "Error");
		}
	);

	constexpr_if<false>()(
		[](auto...){
			static_assert(false, "Error");
		}
	)._else_if<true>(
		[](auto...){
			cout << "2 ";
		}
	)._else(
		[](auto...){
			static_assert(false, "Error");
		}
	);

	constexpr_if<false>()(
		[](auto...){
			static_assert(false, "Error");
		}
	)._else_if<false>(
		[](auto...){
			static_assert(false, "Error");
		}
	)._else_if<true>(
		[](auto...){
			cout << "3 ";
		}
	)._else(
		[](auto...){
			static_assert(false, "Error");
		}
	);

	constexpr_if<false>()(
		[](auto...){
			static_assert(false, "Error");
		}
	)._else(
		[](auto...){
			cout << "4" << endl;
		}
	);

	int c;
	cin >> c;
}

int main() has several tests for this template hack. It successfully outputs "1 2 3 4 " to the standard output, without hitting the static_asserts, thus completely omitting compilation for lambdas for whom the conditions do not hold.

Note that the lambda must necessarily be generic for its body compilation to be omitted when the specialization yields an empty operator().

This topic is closed to new replies.

Advertisement