Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional compilation based on template values?

Tags:

c++

templates

the question posed in: Type condition in template

is very similar, yet the original question wasn't quite answered.

#include "stdafx.h"
#include <type_traits>


class AA {
public:
    double a;

    double Plus(AA &b) {
        return a + b.a;
    }
};

template<class T> double doit(T &t) {
    if (std::is_same<T, AA>::value)
        return t.Plus(t);
    else
        return t + t;
}

int _tmain(int argc, _TCHAR* argv[])
{
    double a;
    AA aa;

    doit(a);
    doit(aa);

    return 0;
}

This doesn't compile, nor did I expect it to. Is something like this possible? Being, based on the template value, I want some code to be compiled, and others not. Here, 'double' doesn't have a method called "Plus" and class "AA" doesn't override the '+' operator. Operator overloading isn't always desirable when considering subtle semantics to the operations, so I'm looking for an alternative. I'd prefer to do #ifdef's (truly conditional compilation as posed in the ref'd question), but based on template values.

like image 593
Rob Bryce Avatar asked Jan 21 '15 20:01

Rob Bryce


2 Answers

Since C++17 there is static if which is called if-constexpr. The following compiles fine since clang-3.9.1 and gcc-7.1.0, latest MSVC compiler 19.11.25506 handles well too with an option /std:c++17.

template<class T> double doit(T &t) {
    if constexpr (std::is_same_v<T, AA>)
        return t.Plus(t);
    else
        return t + t;
}
like image 168
Wormer Avatar answered Nov 06 '22 00:11

Wormer


What you want is a static if. C++ doesn't have it. There are many ways to work around it, none as good as native support. In addition to the methods specified in the other two answers, you could try tag dispatch.

template<class T> double doitImpl(T &t, std::true_type) {
    return t.Plus(t);
}

template<class T> double doitImpl(T &t, std::false_type) {
    return t+t;
}

template<class T> double doit(T &t) {
    return doitImpl(t, std::is_same<T, AA>);
}
like image 27
Pradhan Avatar answered Nov 06 '22 00:11

Pradhan