0

I want to check at compile time if some string is in a list of strings. So if I use static_assert in the main, this works. But if I want to use static_assert inside a constexpr function it gives me compile errors:

Any idea on why this compile error and how to make this compile time check work?

#include <array>
#include <string_view>

class ClosedList : public std::array< std::string_view, 3>
{
public:    
    constexpr bool hasValue( std::string_view  value) const
    {
        for (auto& e : *this) {
            if (value == e) {
                return true;
            }
        }
        return false;
    }

    constexpr std::string_view value(std::string_view value) const
    {
        static_assert( hasValue( value ), "value not in set");
        return value;

    }
};

int main()
{
    constexpr ClosedList myList = { "red", "green", "blue" };    
    static_assert(myList.hasValue( "red" ), "value not in set" );
    auto value = myList.value("red"); // compile error
}
6
  • 6
    Inside of a constexpr functions, the parameters and this don't count as constexpr. The function doesn't have to be called on a compile-time constant. Commented Nov 6, 2020 at 21:57
  • Possible dupe stackoverflow.com/questions/8626055/… Commented Nov 6, 2020 at 21:57
  • This is a question&answer forum. In the spirit of this forum, please ask a question. The behavior of your compiler seems correct. Please take a tour and read How to Ask. Commented Nov 6, 2020 at 22:07
  • @HolyBlackCat hasValue() uses *this and still is constexpr, so I don't see why value() cannot use this function and still being constexpr. Commented Nov 6, 2020 at 22:08
  • @MartijnBreen: You seem to be misunderstanding what the constexpr modifier on a function does. It causes the compiler to attempt compile-time evaluation IN A CONSTANT CONTEXT. The compiler can always do compile-time evaluation under the as-if rule, but without constexpr the result cannot be used in a constant context. But as HolyBlackCat said, functions marked constexpr can also be used outside constant context, so they can't guarantee that the static_assert parameter is a constant expression. Commented Nov 6, 2020 at 22:18

1 Answer 1

0

If you need to assert something in a constexpr method, just throw. Really. As long as the throw expression isn't actually evaluated in a constant context, it's explicitly allowed to compile and be used in constexpr functions and methods:

if (!hasValue(value)) {
    throw std::runtime_error("value not in set");
}

Then it works like you want:

constexpr ClosedList myList { "a", "b", "c" };
constexpr std::string_view b = myList.value("b"); // ok
constexpr std::string_view d = myList.value("d"); // error, not a constant expression

The compile error even points to the line with the throw so you can see the error, kind of.

Demo: https://godbolt.org/z/da36dz

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.