11

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.
hamster on wheels
  • 2,771
  • 17
  • 50
  • 2
    why downvote? "this can't be done" is an acceptable answer. – hamster on wheels Sep 28 '16 at 09:27
  • If I understood you correctly then this would require overloading on constexpr. — [Cannot be done.](http://stackoverflow.com/a/33192804/1968) – Konrad Rudolph Sep 28 '16 at 10:25
  • @Konrad Rudolph. if i read that answer correctly, it says a function cannot have a `constexpr` argument. I am thinking about specialization by trait instead of redefining `constexpr`.... or if there any way that works. – hamster on wheels Sep 28 '16 at 10:40
  • The upshot is the same: you would *need* a `constexpr` parameter specification, which, as the answer says, doesn’t exist. I don’t think this can be emulated via a trait hough I might be mistaken. Best you’ll be able to achieve is check for whether the argument is a [prvalue](http://en.cppreference.com/w/cpp/language/value_category). But there are non-compile-time values that still satisfy this value category. – Konrad Rudolph Sep 28 '16 at 10:50

2 Answers2

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.

Rene
  • 2,466
  • 1
  • 12
  • 18
  • well. but "a parameter is known/unknown at compile time" is known at compile time. I want to know if the following is possible: If the parameter is known (at compile time), specialize the template as version A; otherwise, specialize the template as version B. – hamster on wheels Sep 28 '16 at 09:44
  • 1
    I have problems imagining a scenario where the type of a parameter should be unknown at compile time. Please provide a source code example. – Rene Sep 28 '16 at 10:32
  • it is not about the type. it is the value. `int a;` alone doesn't specify value. `constexpr int a = 6;` specifies a value that is known at compile time. For `int a; bool b = (a == a);`, the value of `b` is known at compile time. – hamster on wheels Sep 28 '16 at 10:35
  • 1
    Okay, so NOW that we cleared that, could you still provide an example source code? Do you want to implement something like the std::get<> method? – Rene Sep 28 '16 at 10:40
0

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:

Elliott
  • 2,603
  • 2
  • 18
  • 35