Jump to content
  • Advertisement
Sign in to follow this  
Funkymunky

Visual Studio C++ "if constexpr"

This topic is 418 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!