以下は問題のコードの簡単な例です。

#include<iostream>

template<typename T>
constexpr auto func(T f, T g){
    return f() + g();
}

int main(){

    auto f = [](){ return 1; };
    auto g = [](){ return 2; };

    std::cout << func(f, g) << std::endl;

    return 0;
}

このときラムダ式はユニークな型であるので関数オブジェクトfgは別の型です。
なのでfunc(f, g)関数呼び出しは型が一致しないので実体化エラーです。

このときに関数オブジェクトでも関数ポインタでも渡せるようにしたいです。

func<int(*)()>(f, g)func(+f, +g)の様な方法もあると思いますがもともと、関数オブジェクトをテンプレートで渡すこと自体が推奨されていないことなのでしょうか?
std::functionや関数ポインタを引数に取らせるほうがよほどいい方法でしょうか?

追記:7/22 11:34

極端な例ですが

template<typename T>
void f(T a){
    if constexpr(std::is_same_v<T, int>){
        std::cout << a << std::endl;
    }else{
        static_assert([](){ return false; }());
    }
}

void f(int a){...}

とどちらがいいのでしょうか。(上記の例は簡単な型なのでテンプレートを使わないほうが良さそうですが...)