简体   繁体   中英

Specialize if value of a variable is known/unknown at compile time

How to specialize a template function for the case that the value of one of its argument is known/unknown during compile time (before actually compile and run the program)?

I can't figure out how yet.

idea 1:

#include <type_traits>
#include <iostream>
int main(void){
    int a; //value of a is not known at compile time
    bool b = (a == a); //value of b is known at compile time.
    std::is_assignable< constexpr bool, bool >::value
}
//g++ magic.cpp -std=c++14
//error: wrong number of template arguments (1, should be 2)
// std::is_assignable< constexpr bool, bool >::value

Idea 2:

#include <type_traits>
#include <iostream>
int main(void){
    const int a=1;
    int b = (a == a);
    std::cout <<  __builtin_constant_p (a)  << std::endl;
    std::cout <<  __builtin_constant_p (b)  << std::endl;
}
//prints 0 and 0.

Well, I guess you mean the type of the argument, right? Values don't matter for partial template specializations...

Then: This can't be done.

Parameter types for templates must be known at compile time. How else should the compiler produce the correct code?

Also for partial template specializations, the types must be known at compile time for the same reason.

I'm a bit late to the party, and my partial answer may not be very satisfying, but here goes:


Situations where we can't tell from inspection whether a value is known at compile time:

  1. Non-template input values to constexpr functions
  2. Members of types provided by template arguments

I don't know what to do about problem 1 , but for problem 2 we can use SFINAE : looking for a specific member with known name (in the below example it's X ), and trying to send it as a template argument, like so:

// like std::void_t, but for value inputs:
template <auto>
using v_to_void_t = void;

//////////////////////////////////////////////////////////////

template <class, class = void>
struct has_constexpr_X
    : std::false_type {};

template <class T>
struct has_constexpr_X <T, v_to_void_t<T().X>>
    : std::true_type {};

template <class T>
constexpr bool has_constexpr_X_v
    = has_constexpr_X<T>::value;

Example uses:

struct HasStaticConstexprX {
    static constexpr int X = 2;
};

struct HasStaticConstX {
    static const int X; // implied constexpr
};
const int HasStaticConstX::X = 3;

struct HasStaticX {
    static int X;
};
int HasStaticX::X = 4;

struct HasConstX {
    const int X;
};

int main () {
    static_assert(has_constexpr_X_v<HasStaticConstexprX>);
    static_assert(has_constexpr_X_v<HasStaticConstX>);
    static_assert(! has_constexpr_X_v<HasStaticX>);
    static_assert(! has_constexpr_X_v<HasConstX>);
}

Demos:

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