Zebrafish
Zebrafish

Reputation: 14406

How can I have this std::conditional not evaluate an expression based on a type?

I'm having the following problem:

struct MyType
{
    int member;
};

template <typename T>
void func(T a)
{
    using mytypedef = std::conditional<std::is_same_v<T, MyType>, decltype(T::member), char>;
    // If T is MyType I want mytypedef to be of type MyType::member
}

int main()
{
    MyType t{};
    func(t); // Works fine because 'T::member' is an identifier
    func(5); // Fails, 'T::member', undeclared identifier
}

What are the ways I can solve this problem?

Upvotes: 1

Views: 139

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275936

T::member is passed to conditional regardless of which branch the first bool says to take. There is no short circuit. And if it isn't valid, that is a hard error

template<class T>struct has_member{T member;};

using mytypedef = decltype(std::declval<std::conditional_t<std::is_same_v<T, MyType>, T, has_member<char>>>().member);

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 173034

The problem is in func, decltype(T::member) is specified as template argument for std::conditional, and it has to be valid whatever T is.

On way is to make type trait for it.

template <typename T>
struct get_mytype {
    using type = T;
};
template <>
struct get_mytype<MyType> {
    using type = decltype(MyType::member);
};

then

template <typename T>
void func(T a)
{
    using mytypedef = typename get_mytype<std::decay_t<T>>::type;
    // If T is MyType I want mytypedef to be of type MyType::member
}

Upvotes: 1

Related Questions