简体   繁体   中英

Calling non-static constexpr member function in template definition

#include <type_traits>

template<size_t S> struct A
{
    constexpr size_t size() const noexcept { return S; } // Not static on purpose!
};

struct B : public A<123> {};

template <class T>
typename std::enable_if<std::is_base_of_v<A<T().size()>, T>, bool>::type // (*)
f(const T&, const T&) noexcept { return true; }

int main() {
    B b1, b2;
    f(b1, b2);
}

In my original question in (*) line I mistakenly used T()::size() , which is obviously incorrect since size() is not static. The code works with T().size() and std::declval<T>().size() . So the question now is what is the difference and if any of these ways are more correct or better?

You didn't specify which compiler you're using, but gcc's error message offers a big honking clue:

t.C:12:52: error: cannot call member function ‘constexpr size_t A<S>::size() const
[with long unsigned int S = 123; size_t = long unsigned int]’ without object

After adjusting the declaration of the method accordingly:

static constexpr size_t size() noexcept { return S; }

gcc then compiled the shown code without issues.

If your intent is really to have size() be a regular class method, then you'll need to use std::declval instead of invoking it as a static method, in your template.

size is a non-static function and requires an object to call. Make it static and remove const .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM