• Advertisement
Sign in to follow this  

Visual Studio C++ "if constexpr"

Recommended Posts

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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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".

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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().

Edited by Hypersomnia

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement