How to use implicit template type deduction












7















I am trying to write a template to calculate the power of a number during compile time (I am not a template meta-programming expert so any comment is appreciated). Below is the code:



template<typename T, T X, uint64_t P>
struct Pow
{
static constexpr T result = X * Pow<T,X, P - 1>::result;
};
template<typename T, T X>
struct Pow<T, X, 0>
{
static constexpr T result = 1;
};
template<typename T, T X>
struct Pow<T, X, 1>
{
static constexpr T result = X;
};


which I need to call like:



Pow<decltype(4), 4, 2>::result


Question: Is there any way in writing a helper template so that the call skips the decltype? For example:



Pow<4, 2>::result


I have read the following but so far I couldn't see an answer (it seems quite the opposite) this, this, and this.










share|improve this question




















  • 3





    Not a template class, but would a constexpr function work equally well, in your case?

    – Sam Varshavchik
    11 hours ago











  • Thank you for your answer. i was looking at that as well but i am finding it hard to force it to be used in a constrexpr fashion. this is what code looked like: template <typename T> constexpr T Pow(T num, unsigned int pow) { return pow == 0 ? 1 : num * Pow(num, pow - 1); }

    – eucristian
    11 hours ago








  • 2





    All that should be needed is your existing template class, as shown in the question, and a constexpr function that returns Pow<T, x, y>::result; which will be logically equivalent, at compile time, to what you have here.

    – Sam Varshavchik
    11 hours ago













  • I am a bit more afraid of people using it in something std::cout << Pow<2,4> which to my understanding would circumvent the constrexpr-ness of the template. (i might be wrong and it might be the same but my understanding is that this is more contextually dependent as where to keep the constexpresness of it)

    – eucristian
    11 hours ago






  • 2





    Maybe the exponent should be an unsigned type, not a signed type. It will break on Pow<double, 2.0, -1>.

    – aschepler
    9 hours ago
















7















I am trying to write a template to calculate the power of a number during compile time (I am not a template meta-programming expert so any comment is appreciated). Below is the code:



template<typename T, T X, uint64_t P>
struct Pow
{
static constexpr T result = X * Pow<T,X, P - 1>::result;
};
template<typename T, T X>
struct Pow<T, X, 0>
{
static constexpr T result = 1;
};
template<typename T, T X>
struct Pow<T, X, 1>
{
static constexpr T result = X;
};


which I need to call like:



Pow<decltype(4), 4, 2>::result


Question: Is there any way in writing a helper template so that the call skips the decltype? For example:



Pow<4, 2>::result


I have read the following but so far I couldn't see an answer (it seems quite the opposite) this, this, and this.










share|improve this question




















  • 3





    Not a template class, but would a constexpr function work equally well, in your case?

    – Sam Varshavchik
    11 hours ago











  • Thank you for your answer. i was looking at that as well but i am finding it hard to force it to be used in a constrexpr fashion. this is what code looked like: template <typename T> constexpr T Pow(T num, unsigned int pow) { return pow == 0 ? 1 : num * Pow(num, pow - 1); }

    – eucristian
    11 hours ago








  • 2





    All that should be needed is your existing template class, as shown in the question, and a constexpr function that returns Pow<T, x, y>::result; which will be logically equivalent, at compile time, to what you have here.

    – Sam Varshavchik
    11 hours ago













  • I am a bit more afraid of people using it in something std::cout << Pow<2,4> which to my understanding would circumvent the constrexpr-ness of the template. (i might be wrong and it might be the same but my understanding is that this is more contextually dependent as where to keep the constexpresness of it)

    – eucristian
    11 hours ago






  • 2





    Maybe the exponent should be an unsigned type, not a signed type. It will break on Pow<double, 2.0, -1>.

    – aschepler
    9 hours ago














7












7








7








I am trying to write a template to calculate the power of a number during compile time (I am not a template meta-programming expert so any comment is appreciated). Below is the code:



template<typename T, T X, uint64_t P>
struct Pow
{
static constexpr T result = X * Pow<T,X, P - 1>::result;
};
template<typename T, T X>
struct Pow<T, X, 0>
{
static constexpr T result = 1;
};
template<typename T, T X>
struct Pow<T, X, 1>
{
static constexpr T result = X;
};


which I need to call like:



Pow<decltype(4), 4, 2>::result


Question: Is there any way in writing a helper template so that the call skips the decltype? For example:



Pow<4, 2>::result


I have read the following but so far I couldn't see an answer (it seems quite the opposite) this, this, and this.










share|improve this question
















I am trying to write a template to calculate the power of a number during compile time (I am not a template meta-programming expert so any comment is appreciated). Below is the code:



template<typename T, T X, uint64_t P>
struct Pow
{
static constexpr T result = X * Pow<T,X, P - 1>::result;
};
template<typename T, T X>
struct Pow<T, X, 0>
{
static constexpr T result = 1;
};
template<typename T, T X>
struct Pow<T, X, 1>
{
static constexpr T result = X;
};


which I need to call like:



Pow<decltype(4), 4, 2>::result


Question: Is there any way in writing a helper template so that the call skips the decltype? For example:



Pow<4, 2>::result


I have read the following but so far I couldn't see an answer (it seems quite the opposite) this, this, and this.







c++ templates template-meta-programming decltype






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 5 hours ago









Null

1,47861926




1,47861926










asked 11 hours ago









eucristianeucristian

7116




7116








  • 3





    Not a template class, but would a constexpr function work equally well, in your case?

    – Sam Varshavchik
    11 hours ago











  • Thank you for your answer. i was looking at that as well but i am finding it hard to force it to be used in a constrexpr fashion. this is what code looked like: template <typename T> constexpr T Pow(T num, unsigned int pow) { return pow == 0 ? 1 : num * Pow(num, pow - 1); }

    – eucristian
    11 hours ago








  • 2





    All that should be needed is your existing template class, as shown in the question, and a constexpr function that returns Pow<T, x, y>::result; which will be logically equivalent, at compile time, to what you have here.

    – Sam Varshavchik
    11 hours ago













  • I am a bit more afraid of people using it in something std::cout << Pow<2,4> which to my understanding would circumvent the constrexpr-ness of the template. (i might be wrong and it might be the same but my understanding is that this is more contextually dependent as where to keep the constexpresness of it)

    – eucristian
    11 hours ago






  • 2





    Maybe the exponent should be an unsigned type, not a signed type. It will break on Pow<double, 2.0, -1>.

    – aschepler
    9 hours ago














  • 3





    Not a template class, but would a constexpr function work equally well, in your case?

    – Sam Varshavchik
    11 hours ago











  • Thank you for your answer. i was looking at that as well but i am finding it hard to force it to be used in a constrexpr fashion. this is what code looked like: template <typename T> constexpr T Pow(T num, unsigned int pow) { return pow == 0 ? 1 : num * Pow(num, pow - 1); }

    – eucristian
    11 hours ago








  • 2





    All that should be needed is your existing template class, as shown in the question, and a constexpr function that returns Pow<T, x, y>::result; which will be logically equivalent, at compile time, to what you have here.

    – Sam Varshavchik
    11 hours ago













  • I am a bit more afraid of people using it in something std::cout << Pow<2,4> which to my understanding would circumvent the constrexpr-ness of the template. (i might be wrong and it might be the same but my understanding is that this is more contextually dependent as where to keep the constexpresness of it)

    – eucristian
    11 hours ago






  • 2





    Maybe the exponent should be an unsigned type, not a signed type. It will break on Pow<double, 2.0, -1>.

    – aschepler
    9 hours ago








3




3





Not a template class, but would a constexpr function work equally well, in your case?

– Sam Varshavchik
11 hours ago





Not a template class, but would a constexpr function work equally well, in your case?

– Sam Varshavchik
11 hours ago













Thank you for your answer. i was looking at that as well but i am finding it hard to force it to be used in a constrexpr fashion. this is what code looked like: template <typename T> constexpr T Pow(T num, unsigned int pow) { return pow == 0 ? 1 : num * Pow(num, pow - 1); }

– eucristian
11 hours ago







Thank you for your answer. i was looking at that as well but i am finding it hard to force it to be used in a constrexpr fashion. this is what code looked like: template <typename T> constexpr T Pow(T num, unsigned int pow) { return pow == 0 ? 1 : num * Pow(num, pow - 1); }

– eucristian
11 hours ago






2




2





All that should be needed is your existing template class, as shown in the question, and a constexpr function that returns Pow<T, x, y>::result; which will be logically equivalent, at compile time, to what you have here.

– Sam Varshavchik
11 hours ago







All that should be needed is your existing template class, as shown in the question, and a constexpr function that returns Pow<T, x, y>::result; which will be logically equivalent, at compile time, to what you have here.

– Sam Varshavchik
11 hours ago















I am a bit more afraid of people using it in something std::cout << Pow<2,4> which to my understanding would circumvent the constrexpr-ness of the template. (i might be wrong and it might be the same but my understanding is that this is more contextually dependent as where to keep the constexpresness of it)

– eucristian
11 hours ago





I am a bit more afraid of people using it in something std::cout << Pow<2,4> which to my understanding would circumvent the constrexpr-ness of the template. (i might be wrong and it might be the same but my understanding is that this is more contextually dependent as where to keep the constexpresness of it)

– eucristian
11 hours ago




2




2





Maybe the exponent should be an unsigned type, not a signed type. It will break on Pow<double, 2.0, -1>.

– aschepler
9 hours ago





Maybe the exponent should be an unsigned type, not a signed type. It will break on Pow<double, 2.0, -1>.

– aschepler
9 hours ago












2 Answers
2






active

oldest

votes


















11














Starting from C++17, you can use an auto type for the X template value



template <auto X, int64_t P>
struct Pow
{
static constexpr decltype(X) result = X * Pow<X, P - 1>::result;
};

template <auto X>
struct Pow<X, 0>
{
static constexpr decltype(X) result = 1;
};


And you can also see that, given the 0 partial specialization, the 1 partial specialization is superfluous (also C++11/C++14).



Before C++17... the best I can imagine, to avoid to explicit the T type, pass through a macro definition (that usually is heavily discouraged but, in this case, I suppose can be reasonable).



Something as



#define PowMacro(X, P)  Pow<decltype(X), X, P> 





share|improve this answer





















  • 2





    "The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

    – aschepler
    9 hours ago








  • 1





    @aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

    – max66
    6 hours ago





















7














Sure you can skip the decltype, and you need no structures when using C++ 11 contexpr. For example:



#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

return 0;
}


P.S.
Faster way for racing number in a power. Real code should use something like that since compilation time also does matters.



#include <iostream>
#include <type_traits>

// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
template<typename T>
constexpr T pow(const T base,const T power, typename std::enable_if< std::is_integral<T>::value >::type* = 0) {
return 1 == power
? base
: 0 == power
? 1
: (1 == (power & 1) )
? base * pow(base, power - 1)
: pow(base, (power >> 1) ) * pow( base, (power >> 1) );
}


#ifdef __GNUG__

// GCC able to use most of <cmath> at compile time, check <cmath> header

inline constexpr float pow(float base, float power) noexcept {
return __builtin_powf(base, power);
}

inline constexpr double pow(double base, double power) noexcept {
return __builtin_pow(base, power);
}

inline constexpr long double pow(long double base,long double power) noexcept {
return __builtin_powl(base, power);
}

#else

// slow
template<typename T>
constexpr T pow(T base, T power, typename std::enable_if< std::is_floating_point<T>::value >::type* = 0) noexcept {
return power == 1.0 ? base : base * pow(base,power - static_cast<T>(1.0) );
}

#endif // __GNUG__


int main(int argc, const char** argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 1024 == pow(2L,10L) ,"wrong pow");
static_assert( (1 << 20) == pow(2LL,20LL) ,"wrong pow");

std::cout << "integer 2^1=" << pow(2, 1) << std::endl;
std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "long 2^10=" << pow(2L, 10L) << std::endl;
std::cout << "long long 2^20=" << pow(2LL, 20LL) << std::endl;

static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");
static_assert( 1024.0L == pow(2.0L,10.0L) ,"wrong pow");

std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;
std::cout << "long double 2^10=" << pow(2.0L, 10.0L) << std::endl;

return 0;
}





share|improve this answer





















  • 1





    Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

    – eucristian
    10 hours ago













  • constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

    – Victor Gubin
    10 hours ago








  • 1





    BTW, the best way to check - compiler assembly output.

    – Victor Gubin
    10 hours ago






  • 2





    If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

    – Caleth
    9 hours ago











  • when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

    – fdan
    9 hours ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54748610%2fhow-to-use-implicit-template-type-deduction%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









11














Starting from C++17, you can use an auto type for the X template value



template <auto X, int64_t P>
struct Pow
{
static constexpr decltype(X) result = X * Pow<X, P - 1>::result;
};

template <auto X>
struct Pow<X, 0>
{
static constexpr decltype(X) result = 1;
};


And you can also see that, given the 0 partial specialization, the 1 partial specialization is superfluous (also C++11/C++14).



Before C++17... the best I can imagine, to avoid to explicit the T type, pass through a macro definition (that usually is heavily discouraged but, in this case, I suppose can be reasonable).



Something as



#define PowMacro(X, P)  Pow<decltype(X), X, P> 





share|improve this answer





















  • 2





    "The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

    – aschepler
    9 hours ago








  • 1





    @aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

    – max66
    6 hours ago


















11














Starting from C++17, you can use an auto type for the X template value



template <auto X, int64_t P>
struct Pow
{
static constexpr decltype(X) result = X * Pow<X, P - 1>::result;
};

template <auto X>
struct Pow<X, 0>
{
static constexpr decltype(X) result = 1;
};


And you can also see that, given the 0 partial specialization, the 1 partial specialization is superfluous (also C++11/C++14).



Before C++17... the best I can imagine, to avoid to explicit the T type, pass through a macro definition (that usually is heavily discouraged but, in this case, I suppose can be reasonable).



Something as



#define PowMacro(X, P)  Pow<decltype(X), X, P> 





share|improve this answer





















  • 2





    "The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

    – aschepler
    9 hours ago








  • 1





    @aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

    – max66
    6 hours ago
















11












11








11







Starting from C++17, you can use an auto type for the X template value



template <auto X, int64_t P>
struct Pow
{
static constexpr decltype(X) result = X * Pow<X, P - 1>::result;
};

template <auto X>
struct Pow<X, 0>
{
static constexpr decltype(X) result = 1;
};


And you can also see that, given the 0 partial specialization, the 1 partial specialization is superfluous (also C++11/C++14).



Before C++17... the best I can imagine, to avoid to explicit the T type, pass through a macro definition (that usually is heavily discouraged but, in this case, I suppose can be reasonable).



Something as



#define PowMacro(X, P)  Pow<decltype(X), X, P> 





share|improve this answer















Starting from C++17, you can use an auto type for the X template value



template <auto X, int64_t P>
struct Pow
{
static constexpr decltype(X) result = X * Pow<X, P - 1>::result;
};

template <auto X>
struct Pow<X, 0>
{
static constexpr decltype(X) result = 1;
};


And you can also see that, given the 0 partial specialization, the 1 partial specialization is superfluous (also C++11/C++14).



Before C++17... the best I can imagine, to avoid to explicit the T type, pass through a macro definition (that usually is heavily discouraged but, in this case, I suppose can be reasonable).



Something as



#define PowMacro(X, P)  Pow<decltype(X), X, P> 






share|improve this answer














share|improve this answer



share|improve this answer








edited 9 hours ago

























answered 11 hours ago









max66max66

36.8k74166




36.8k74166








  • 2





    "The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

    – aschepler
    9 hours ago








  • 1





    @aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

    – max66
    6 hours ago
















  • 2





    "The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

    – aschepler
    9 hours ago








  • 1





    @aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

    – max66
    6 hours ago










2




2





"The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

– aschepler
9 hours ago







"The 1 partial specialization is superfluous"... unless T is a class type representing some sort of mathematical ring without unit or semigroup, or otherwise for some reason does not support initialization from the expression 1.

– aschepler
9 hours ago






1




1





@aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

– max66
6 hours ago







@aschepler - good point... from the theoretical point of view... but, practically speaking, which T type, the values of witch can be template parameters, can't accept initialization from 1 but support multiplication?

– max66
6 hours ago















7














Sure you can skip the decltype, and you need no structures when using C++ 11 contexpr. For example:



#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

return 0;
}


P.S.
Faster way for racing number in a power. Real code should use something like that since compilation time also does matters.



#include <iostream>
#include <type_traits>

// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
template<typename T>
constexpr T pow(const T base,const T power, typename std::enable_if< std::is_integral<T>::value >::type* = 0) {
return 1 == power
? base
: 0 == power
? 1
: (1 == (power & 1) )
? base * pow(base, power - 1)
: pow(base, (power >> 1) ) * pow( base, (power >> 1) );
}


#ifdef __GNUG__

// GCC able to use most of <cmath> at compile time, check <cmath> header

inline constexpr float pow(float base, float power) noexcept {
return __builtin_powf(base, power);
}

inline constexpr double pow(double base, double power) noexcept {
return __builtin_pow(base, power);
}

inline constexpr long double pow(long double base,long double power) noexcept {
return __builtin_powl(base, power);
}

#else

// slow
template<typename T>
constexpr T pow(T base, T power, typename std::enable_if< std::is_floating_point<T>::value >::type* = 0) noexcept {
return power == 1.0 ? base : base * pow(base,power - static_cast<T>(1.0) );
}

#endif // __GNUG__


int main(int argc, const char** argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 1024 == pow(2L,10L) ,"wrong pow");
static_assert( (1 << 20) == pow(2LL,20LL) ,"wrong pow");

std::cout << "integer 2^1=" << pow(2, 1) << std::endl;
std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "long 2^10=" << pow(2L, 10L) << std::endl;
std::cout << "long long 2^20=" << pow(2LL, 20LL) << std::endl;

static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");
static_assert( 1024.0L == pow(2.0L,10.0L) ,"wrong pow");

std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;
std::cout << "long double 2^10=" << pow(2.0L, 10.0L) << std::endl;

return 0;
}





share|improve this answer





















  • 1





    Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

    – eucristian
    10 hours ago













  • constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

    – Victor Gubin
    10 hours ago








  • 1





    BTW, the best way to check - compiler assembly output.

    – Victor Gubin
    10 hours ago






  • 2





    If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

    – Caleth
    9 hours ago











  • when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

    – fdan
    9 hours ago
















7














Sure you can skip the decltype, and you need no structures when using C++ 11 contexpr. For example:



#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

return 0;
}


P.S.
Faster way for racing number in a power. Real code should use something like that since compilation time also does matters.



#include <iostream>
#include <type_traits>

// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
template<typename T>
constexpr T pow(const T base,const T power, typename std::enable_if< std::is_integral<T>::value >::type* = 0) {
return 1 == power
? base
: 0 == power
? 1
: (1 == (power & 1) )
? base * pow(base, power - 1)
: pow(base, (power >> 1) ) * pow( base, (power >> 1) );
}


#ifdef __GNUG__

// GCC able to use most of <cmath> at compile time, check <cmath> header

inline constexpr float pow(float base, float power) noexcept {
return __builtin_powf(base, power);
}

inline constexpr double pow(double base, double power) noexcept {
return __builtin_pow(base, power);
}

inline constexpr long double pow(long double base,long double power) noexcept {
return __builtin_powl(base, power);
}

#else

// slow
template<typename T>
constexpr T pow(T base, T power, typename std::enable_if< std::is_floating_point<T>::value >::type* = 0) noexcept {
return power == 1.0 ? base : base * pow(base,power - static_cast<T>(1.0) );
}

#endif // __GNUG__


int main(int argc, const char** argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 1024 == pow(2L,10L) ,"wrong pow");
static_assert( (1 << 20) == pow(2LL,20LL) ,"wrong pow");

std::cout << "integer 2^1=" << pow(2, 1) << std::endl;
std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "long 2^10=" << pow(2L, 10L) << std::endl;
std::cout << "long long 2^20=" << pow(2LL, 20LL) << std::endl;

static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");
static_assert( 1024.0L == pow(2.0L,10.0L) ,"wrong pow");

std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;
std::cout << "long double 2^10=" << pow(2.0L, 10.0L) << std::endl;

return 0;
}





share|improve this answer





















  • 1





    Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

    – eucristian
    10 hours ago













  • constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

    – Victor Gubin
    10 hours ago








  • 1





    BTW, the best way to check - compiler assembly output.

    – Victor Gubin
    10 hours ago






  • 2





    If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

    – Caleth
    9 hours ago











  • when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

    – fdan
    9 hours ago














7












7








7







Sure you can skip the decltype, and you need no structures when using C++ 11 contexpr. For example:



#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

return 0;
}


P.S.
Faster way for racing number in a power. Real code should use something like that since compilation time also does matters.



#include <iostream>
#include <type_traits>

// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
template<typename T>
constexpr T pow(const T base,const T power, typename std::enable_if< std::is_integral<T>::value >::type* = 0) {
return 1 == power
? base
: 0 == power
? 1
: (1 == (power & 1) )
? base * pow(base, power - 1)
: pow(base, (power >> 1) ) * pow( base, (power >> 1) );
}


#ifdef __GNUG__

// GCC able to use most of <cmath> at compile time, check <cmath> header

inline constexpr float pow(float base, float power) noexcept {
return __builtin_powf(base, power);
}

inline constexpr double pow(double base, double power) noexcept {
return __builtin_pow(base, power);
}

inline constexpr long double pow(long double base,long double power) noexcept {
return __builtin_powl(base, power);
}

#else

// slow
template<typename T>
constexpr T pow(T base, T power, typename std::enable_if< std::is_floating_point<T>::value >::type* = 0) noexcept {
return power == 1.0 ? base : base * pow(base,power - static_cast<T>(1.0) );
}

#endif // __GNUG__


int main(int argc, const char** argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 1024 == pow(2L,10L) ,"wrong pow");
static_assert( (1 << 20) == pow(2LL,20LL) ,"wrong pow");

std::cout << "integer 2^1=" << pow(2, 1) << std::endl;
std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "long 2^10=" << pow(2L, 10L) << std::endl;
std::cout << "long long 2^20=" << pow(2LL, 20LL) << std::endl;

static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");
static_assert( 1024.0L == pow(2.0L,10.0L) ,"wrong pow");

std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;
std::cout << "long double 2^10=" << pow(2.0L, 10.0L) << std::endl;

return 0;
}





share|improve this answer















Sure you can skip the decltype, and you need no structures when using C++ 11 contexpr. For example:



#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if< std::is_arithmetic<T>::value >::type >
constexpr T pow(T n, T power) noexcept {
return power == 1 ? n : n * pow(n,power - 1);
}

int main(int argc, const char* argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");

std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;

return 0;
}


P.S.
Faster way for racing number in a power. Real code should use something like that since compilation time also does matters.



#include <iostream>
#include <type_traits>

// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
template<typename T>
constexpr T pow(const T base,const T power, typename std::enable_if< std::is_integral<T>::value >::type* = 0) {
return 1 == power
? base
: 0 == power
? 1
: (1 == (power & 1) )
? base * pow(base, power - 1)
: pow(base, (power >> 1) ) * pow( base, (power >> 1) );
}


#ifdef __GNUG__

// GCC able to use most of <cmath> at compile time, check <cmath> header

inline constexpr float pow(float base, float power) noexcept {
return __builtin_powf(base, power);
}

inline constexpr double pow(double base, double power) noexcept {
return __builtin_pow(base, power);
}

inline constexpr long double pow(long double base,long double power) noexcept {
return __builtin_powl(base, power);
}

#else

// slow
template<typename T>
constexpr T pow(T base, T power, typename std::enable_if< std::is_floating_point<T>::value >::type* = 0) noexcept {
return power == 1.0 ? base : base * pow(base,power - static_cast<T>(1.0) );
}

#endif // __GNUG__


int main(int argc, const char** argv) {

static_assert( 4 == pow(2,2) ,"wrong pow");
static_assert( 1024 == pow(2L,10L) ,"wrong pow");
static_assert( (1 << 20) == pow(2LL,20LL) ,"wrong pow");

std::cout << "integer 2^1=" << pow(2, 1) << std::endl;
std::cout << "integer 2^2=" << pow(2, 2) << std::endl;
std::cout << "long 2^10=" << pow(2L, 10L) << std::endl;
std::cout << "long long 2^20=" << pow(2LL, 20LL) << std::endl;

static_assert( 8.0F == pow(2.0F,3.0F) ,"wrong pow");
static_assert( 256.0 == pow(2.0,8.0) ,"wrong pow");
static_assert( 1024.0L == pow(2.0L,10.0L) ,"wrong pow");

std::cout << "float 2^3=" << pow(2.0F, 3.0F) << std::endl;
std::cout << "double 2^8=" << pow(2.0, 8.0) << std::endl;
std::cout << "long double 2^10=" << pow(2.0L, 10.0L) << std::endl;

return 0;
}






share|improve this answer














share|improve this answer



share|improve this answer








edited 4 hours ago

























answered 11 hours ago









Victor GubinVictor Gubin

1,468212




1,468212








  • 1





    Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

    – eucristian
    10 hours ago













  • constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

    – Victor Gubin
    10 hours ago








  • 1





    BTW, the best way to check - compiler assembly output.

    – Victor Gubin
    10 hours ago






  • 2





    If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

    – Caleth
    9 hours ago











  • when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

    – fdan
    9 hours ago














  • 1





    Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

    – eucristian
    10 hours ago













  • constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

    – Victor Gubin
    10 hours ago








  • 1





    BTW, the best way to check - compiler assembly output.

    – Victor Gubin
    10 hours ago






  • 2





    If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

    – Caleth
    9 hours ago











  • when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

    – fdan
    9 hours ago








1




1





Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

– eucristian
10 hours ago







Thank you for your answer. I have also read this but i have a question. Without the static_assert bit there would be no way to guarantee the compile time calculated. Is this correct?

– eucristian
10 hours ago















constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

– Victor Gubin
10 hours ago







constexpr so in case of something like long double foo(long double bar, float buz) { return log(bar,MATH_PI) * pow(bar, sqrt(buz) ) ; } off cause it is not going to be a compile time. But in this case i think - it should not be a compile time. Unlike something like static constexpr long double FOO = pow(128.0,500.0D);

– Victor Gubin
10 hours ago






1




1





BTW, the best way to check - compiler assembly output.

– Victor Gubin
10 hours ago





BTW, the best way to check - compiler assembly output.

– Victor Gubin
10 hours ago




2




2





If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

– Caleth
9 hours ago





If you want a compile time error when the arguments to pow are not constexpr, you can just static_assert(n == n, "not constexpr call"); static_assert(power == power, "not constexpr call");

– Caleth
9 hours ago













when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

– fdan
9 hours ago





when you invoke the function in a compile-time context (either by storing the result as constexpr or by using static_assert) your compiler will automatically fail to compile with some kind of "no constexpr"-message. I don't see any value in checking the parameters for constants...

– fdan
9 hours ago


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54748610%2fhow-to-use-implicit-template-type-deduction%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Hivernacle

Fluorita

Hulsita