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

2

12

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.
Acidosis answered 28/9, 2016 at 9:11 Comment(4)
why downvote? "this can't be done" is an acceptable answer.Acidosis
If I understood you correctly then this would require overloading on constexpr. — Cannot be done.Traveled
@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.Acidosis
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. But there are non-compile-time values that still satisfy this value category.Traveled
D
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.

Disannul answered 28/9, 2016 at 9:37 Comment(4)
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.Acidosis
I have problems imagining a scenario where the type of a parameter should be unknown at compile time. Please provide a source code example.Disannul
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.Acidosis
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?Disannul
W
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:

Waldowaldon answered 8/4, 2022 at 17:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.